Accessing Interaction Hint Information¶
Problem¶
You want to perceive protein-ligand interaction hints and retrieve interaction information.
Difficulty Level¶
Solution¶
This recipe discusses several examples that show how to perceive and access interaction information.
Hint
If you would like to learn about interaction API before diving into the examples, please see the Overview of OEChem TK Interaction API subsection first.
Perceiving Interaction Hints¶
The example below shows how to initialize an interaction container (OEInteractionHintContainer) with a ligand and a protein and then perceive interaction hints between them by calling the OEPerceiveInteractionHints function. If the container can not be initialized with the given molecules, the OEIsValidActiveSite function returns False.
def perceive_interation_hints(protein, ligand):
"""
:type protein: oechem.OEMol
:type ligand: oechem.OEMol
:rtype: oechem.OEInteractionHintContainer
"""
asite = oechem.OEInteractionHintContainer()
asite.AddMolecule(protein, oechem.OEProteinInteractionHintComponent())
asite.AddMolecule(ligand, oechem.OELigandInteractionHintComponent())
if not oechem.OEIsValidActiveSite(asite):
oechem.OEThrow.Fatal("Cannot initialize active site!")
oechem.OEPerceiveInteractionHints(asite)
return asite
See also
See Table 1 for list of interaction types that are currently perceived in OEChem TK.
The previous example shows how to perceive protein-ligand interaction hints using the default geometric constraints. These parameters can be customized by using the OEPerceiveInteractionOptions class. The example below illustrates how to reduce the default distance constraints used to determine Pi and T stacking by 0.5 Ångströms.
def perceive_interation_hints_user_def_params(protein, ligand):
"""
:type protein: oechem.OEMol
:type ligand: oechem.OEMol
:rtype: oechem.OEInteractionHintContainer
"""
asite = oechem.OEInteractionHintContainer()
asite.AddMolecule(protein, oechem.OEProteinInteractionHintComponent())
asite.AddMolecule(ligand, oechem.OELigandInteractionHintComponent())
if not oechem.OEIsValidActiveSite(asite):
oechem.OEThrow.Fatal("Cannot initialize active site!")
opts = oechem.OEPerceiveInteractionOptions()
opts.SetMaxPiStackDistance(opts.GetMaxPiStackDistance() - 0.5)
opts.SetMaxTStackDistance(opts.GetMaxTStackDistance() - 0.5)
oechem.OEPerceiveInteractionHints(asite, opts)
return asite
See also
- Overview of OEChem TK Interaction API subsection
The following API in OEChem TK manual:
- OEProteinInteractionHintComponent and OELigandInteractionHintComponent classes
- OEInteractionHintContainer class
- OEIsValidActiveSite function
- OEPerceiveInteractionOptions class
- OEPerceiveInteractionHints function
Accessing Interactions¶
This subsection show several examples about how to iterate over interactions and access information from them.
The first simple code snippet shows how to loop over the interactions and count them. The OEInteractionHintContainer.GetInteractions method returns an iterator over all the OEInteractionHint object stored in the container.
def num_interactions(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
nrinters = len([i for i in asite.GetInteractions()])
return nrinters
The next code snippet shows how to count only the intra-molecular interactions by utilizing the OEInteractionHint.IsIntra method.
def num_intra_interactions(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
nrintras = 0
for i in asite.GetInteractions():
if i.IsIntra():
nrintras += 1
return nrintras
Alternatively, you can use the OEIsIntraInteractionHint interaction predicates to do the same. If a predicate is passed to the OEInteractionHintContainer.GetInteractions method, it only returns interactions which satisfy the given predicate.
def num_intra_interactions_predicate(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
nrintras = len([i for i in asite.GetInteractions(oechem.OEIsIntraInteractionHint())])
return nrintras
See also
See the Interaction predicates subsection for the list of interaction predicates available in OEChem TK,
Even though OEChem TK provides a wide selection of built-in interaction predicates, a need might arise to write user-defined predicates. The following two examples show how to implement and utilize your own predicates.
In the first example, the IsCarbonContactInteraction predicate returns True for contact interaction type between two carbon atoms. It uses the OEInteractionHint.GetBgnFragment and OEInteractionHint.GetEndFragment methods to retrieve the two interacting fragments (OEInteractionHintFragment) stored in the OEInteractionHint object.
class IsCarbonContactInteraction(oechem.OEUnaryInteractionHintPred):
def __call__(self, inter):
"""
:type inter: oechem.OEInteractionHint
:rtype: boolean
"""
# check the type if the interactions
if inter.GetInteractionType() != oechem.OEContactInteractionHint():
return False
# check that the interaction is between two carbon atoms
for frag in [inter.GetBgnFragment(), inter.GetEndFragment()]:
catom = frag.GetAtom(oechem.OEIsCarbon())
if catom is None:
return False
return True
A user-defines predicates can be used exactly the same way as the built-in ones:
def num_carbon_contact_interactions(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
nrinters = len([i for i in asite.GetInteractions(IsCarbonContactInteraction())])
return nrinters
The predicate of the second example is a bit more complicated and shows how the OEHasResidueInteractionHint built-in predicate has been implemented in OEChem TK. The HasResidueInteraction returns True if the OEInteractionHint object stores interaction for the given residue (OEResidue).
class HasResidueInteraction(oechem.OEUnaryInteractionHintPred):
def __init__(self, res):
oechem.OEUnaryInteractionHintPred.__init__(self)
self.residue = res
self.atompred = oechem.OEAtomIsInResidue(res)
def __call__(self, inter):
"""
:type inter: oechem.OEInteractionHint
:rtype: boolean
"""
for frag in [inter.GetBgnFragment(), inter.GetEndFragment()]:
for atom in frag.GetAtoms(self.atompred):
return True
return False
def CreateCopy(self):
return HasResidueInteraction(self.residue).__disown__()
The following code snippet counts the number of interactions for the ‘TRP-275-A’ residue.
def num_residue_interactions(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
res = oechem.OEResidue()
res.SetName('TRP')
res.SetChainID('A')
res.SetResidueNumber(275)
nrinters = len([i for i in asite.GetInteractions(HasResidueInteraction(res))])
return nrinters
OEChem TK predicates can be combined with logical operations. The example below count the number of stacking interaction for the ‘TRP-275-A’ residue.
def num_stacking_residue_interactions(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: int
"""
res = oechem.OEResidue()
res.SetName('TRP')
res.SetChainID('A')
res.SetResidueNumber(275)
respred = HasResidueInteraction(res)
stackingpred = oechem.OEIsStackingInteractionHint()
nrinters = len([i for i in asite.GetInteractions(oechem.OEAndInteractionHint(respred, stackingpred))])
return nrinters
Similarly you can use the OEOrInteractionHint and OENotInteractionHint logical operations combine built-in and user-defined predicates to express complex conditions.
Accessing Interaction Atoms¶
This subsection show several examples about how to access the atom of an interaction. The first two code snippets show how to retrieve ligand atoms that are belong to any interactions stored in the given interaction container.
In the first code snippet, the ligand component of an interaction container is retrieved, then the atoms of the ligand molecule are being looped over and checked whether they belong to any of the interactions stored in the container by calling the OEInteractionHintContainer.HasInteraction method. This method returns True if there is at least one interaction that matches the given predicate. In this example the predicate is OEHasInteractionHint that identifies interactions with the given atom. You can find out more about interaction predicates in the Accessing Interactions subsection.
def get_ligand_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
for atom in ligand.GetAtoms():
if asite.HasInteraction(oechem.OEHasInteractionHint(atom)):
atoms.append(atom)
return atoms
In the second example, the interaction of the container are looped over. Each interaction stores two fragments (OEInteractionHintFragment). If a fragment is belong to the ligand component then its atoms are added to ligand atom set.
It is important to collect the ligand atoms in a set (rather than in a list as in the previous example). While in the previous example, atom can be added to a list only once, in the second example, when looping over interactions, a ligand atom can be encountered more than once since an atom can belong to more than one interactions.
def get_ligand_frag_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = set()
for inter in asite.GetInteractions():
for frag in [inter.GetBgnFragment(), inter.GetEndFragment()]:
if frag.GetComponentType() == oechem.OELigandInteractionHintComponent():
for atom in frag.GetAtoms():
atoms.add(atom)
return list(atoms)
If you want to access protein atoms, you have to replace the OELigandInteractionHintComponent type with OEProteinInteractionHintComponent in the previous two examples. For example:
def get_protein_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = list()
protein = asite.GetMolecule(oechem.OEProteinInteractionHintComponent())
for atom in protein.GetAtoms():
if asite.HasInteraction(oechem.OEHasInteractionHint(atom)):
atoms.append(atom)
return atoms
In the following examples, atom predicates are used to collect only the subset of the ligand atoms. The code snippet below demonstrates how to retrieve only nitrogen ligand atoms. It uses the OEIsNitrogen atom predicate which is one of built-in predicate available in OEChem TK.
def get_ligand_nitrogen_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
for atom in ligand.GetAtoms(oechem.OEIsNitrogen()):
if asite.HasInteraction(oechem.OEHasInteractionHint(atom)):
atoms.append(atom)
return atoms
See also
See the Atom predicates subsection for the list of atom predicates available in OEChem TK
Even though OEChem TK provides a wide selection of built-in atom predicates, a need might arise to write s user-defined predicate. The following examples shows how to implement and utilize such a predicate.
class HasAtomicNumber(oechem.OEUnaryAtomPred):
def __init__(self, alist):
oechem.OEUnaryAtomPred.__init__(self)
self.atomic_list = alist
def __call__(self, atom):
"""
:type asite: oechem.OEAtomBase
:rtype: boolean
"""
return (atom.GetAtomicNum() in self.atomic_list)
def CreateCopy(self):
return HasAtomicNumber(self.atomic_list).__disown__()
def get_ligand_oxygen_nitrogen_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
atompred = HasAtomicNumber([oechem.OEElemNo_O, oechem.OEElemNo_N])
for atom in ligand.GetAtoms(atompred):
if asite.HasInteraction(oechem.OEHasInteractionHint(atom)):
atoms.append(atom)
return atoms
OEChem TK predicates can be combined with logical operations. In the example below only chain nitrogen that belong to interactions are collected.
def get_ligand_chain_nitrogen_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
for atom in ligand.GetAtoms(oechem.OEAndAtom(oechem.OEIsNitrogen(), oechem.OEAtomIsInChain())):
if asite.HasInteraction(oechem.OEHasInteractionHint(atom)):
atoms.append(atom)
return atoms
Similarly you can use the OEOrAtom and OENotAtom logical operations combine built-in predicates and express complex conditions.
The interaction perceived by the OEPerceiveInteractionHints function are typed. See Table 1 for list of interaction types that are currently perceived in OEChem TK. This means that is quite easy to iterate over atoms and check whether they belong to a specific interaction type.
The code snippet below collects ligand atoms which part of a stacking interaction utilizing the OEIsStackingInteractionHint build-in predicate.
def get_ligand_stacking_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
stackingpred = oechem.OEIsStackingInteractionHint()
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
for atom in ligand.GetAtoms():
if asite.HasInteraction(oechem.OEAndInteractionHint(oechem.OEHasInteractionHint(atom), stackingpred)):
atoms.append(atom)
return atoms
See also
See the Interaction predicates subsection for the list of interaction predicates available in OEChem TK,
Some interactions type is also associated with a namespace that enables to subtype the interaction. For example, the OEStackingInteractionHintType namespace corresponds to the OEStackingInteractionHint interaction type. The following example shows how to access ligand atoms that are in a Pi-stacking interaction.
def get_ligand_pi_stacking_atoms(asite):
"""
:type asite: oechem.OEInteractionHintContainer
:rtype: list[oechem.OEAtomBase]
"""
stackingsubtype = oechem.OEStackingInteractionHint(oechem.OEStackingInteractionHintType_Pi)
stackingpred = oechem.OEHasInteractionHintType(stackingsubtype)
atoms = list()
ligand = asite.GetMolecule(oechem.OELigandInteractionHintComponent())
for atom in ligand.GetAtoms():
if asite.HasInteraction(oechem.OEAndInteractionHint(oechem.OEHasInteractionHint(atom), stackingpred)):
atoms.append(atom)
return atoms
See also
- Overview of OEChem TK Interaction API subsection
- Interaction predicates subsection
Discussion¶
Overview of OEChem TK Interaction API¶
OEChem TK provides the following API to perceive protein-ligand interactions:
- OEPerceiveInteractionHints
- The function that perceives protein-ligand interactions.
- OEPerceiveInteractionOptions
The class that stores the parameters that control the interaction perception.
The default geometric parameters have been set based on literature data ([Kumar-2002], [Cavallo-2016], [Bissantz-2010], and [Marcou-2007] ).
Code examples
- Perceiving Interaction Hints subsection
OEChem TK provides the following API to store and access protein-ligand interactions:
- OEInteractionHintContainer
- This is the main container that stores typed molecules (OEMolBase), fragments of those molecules (OEInteractionHintFragment) and typed interactions (OEInteractionHint) between the fragments.
- OEInteractionHintComponentTypeBase
The abstract class that enables to type molecules stored in the interaction container. Each molecule added to the container has to have a specific type. Currently, there are two built-in component types available:
- OELigandInteractionHintComponent – component type that classifies a molecule as a ‘ligand’
- OEProteinInteractionHintComponent – component type that classifies a molecule as a ‘protein’
- OEInteractionHintFragment
- Set of atoms of a molecule that is stored in the interaction container. These are the atoms that are contribute to an interaction (OEInteractionHint). Some interactions such as hydrogen bonds are between two atoms, other ones define interactions between set of atoms. For example a stacking interaction is between atoms of two aromatic ring systems.
- OEInteractionHint
- An iteration is defined between two fragments (OEInteractionHintFragment) stored in the container. An interaction can be either inter (OEInteractionHint.IsInter) or intra (OEInteractionHint.IsIntra) molecular. Each interaction has a specific type that is derived from the OEInteractionHintTypeBase class.
- OEInteractionHintTypeBase
The abstract class that enables to type interactions stored in the interaction container. The table below shows the specific interaction types currently available in OEChem TK. Some interaction classes are also associated with namespaces that enable to subtype the main interaction types. For example, the stacking interaction have two subtypes:
- Pi-stacking – OEStackingInteractionHint ( OEStackingInteractionHintType_Pi )
- T-stacking – OEStackingInteractionHint ( OEStackingInteractionHintType_T )
Table 1. Interaction types currently available in OEChem TK name corresponding interaction class corresponding interaction type namespace cation-pi OECationPiInteractionHint OECationPiInteractionHintType chelator OEChelatorInteractionHint OEChelatorInteractionHintType clash OEClashInteractionHint None contact OEContactInteractionHint None covalent OECovalentInteractionHint None halogen bond OEHalogenBondInteractionHint OEHalogenBondInteractionHintType hydrogen bond OEHBondInteractionHint OEHBondInteractionHintType salt-bridge OESaltBridgeInteractionHint OESaltBridgeInteractionHintType stacking (T and Pi) OEStackingInteractionHint OEStackingInteractionHintType
Other related API:
- OEIsValidActiveSite
- The function that checks whether the interaction container initialized correctly as active site i.e. containing two molecules: one typed as ligand and one typed as protein.
- OEGetActiveSiteInteractionHintTypes
- The function that iterates over all interaction types (including subtypes) that are perceived by the OEPerceiveInteractionHints function.
Atom predicates¶
OEChem TK provides an extensive set of built-in atom predicates, the most common ones are listed in the following table.
Access | Functor Name |
---|---|
aromatic atoms | OEIsAromaticAtom |
ring atoms | OEAtomIsInRing |
chain atoms | OEAtomIsInChain |
atoms with specified residue | OEAtomIsInResidue |
atoms with specified atomic number | OEHasAtomicNum |
hetero atoms | OEIsHetero |
The following logical operations allow to combine both the built-in and the user defined atom predicates.
Logical operation | Composite Functor Name |
---|---|
Logical and | OEAndAtom |
Logical or | OEOrAtom |
Logical not | OENotAtom |
See also
For the full list of atom predicates, see more information in the following sections on the OEChem TK manual:
- Atom Functors section
- Atomic Number Functors section
- Composition Functors section
Code examples
- Accessing Interaction Atoms subsection
Interaction predicates¶
The table below list all interaction predicates that are currently available in OEChem TK.
The following logical operations allow to combine both the built-in and the user defined interaction predicates.
Logical operation | Composite Functor Name |
---|---|
Logical and | OEAndInteractionHint |
Logical or | OEOrInteractionHint |
Logical not | OENotInteractionHint |
Code examples
- Accessing Interactions subsection
See also in OEChem TK manual¶
API
- OEHasInteractionHintType predicate
- OEInteractionHint class
- OEInteractionHintContainer class
- OELigandInteractionHintComponent class
- OEPerceiveInteractionHints function
- OEPerceiveInteractionOptions class
- OEProteinInteractionHintComponent class
- OEResidue class