Stereochemistry Perception

OEChem has the ability to store and retrieve stereochemical information for atoms and bonds independent of two or three dimensional coordinates. The current version of OEChem supports stereochemistry definitions of handedness around tetrahedral centers, and cis/trans configuration around bonds.

Atom Chirality

The following two code snippets demonstrate how to loop over chiral atoms using the OEIsChiralAtom functor and the IsChiral method of the OEAtomBase class.

for (OEAtomBase atom : mol.GetAtoms(new OEIsChiralAtom())) {
    System.out.println(atom.GetIdx() + " " + oechem.OEGetAtomicSymbol(atom.GetAtomicNum()));
}
for (OEAtomBase atom : mol.GetAtoms()) {
    if (atom.IsChiral()) {
        System.out.println(atom.GetIdx() + " " + oechem.OEGetAtomicSymbol(atom.GetAtomicNum()));
    }
}

Warning

When a molecule is imported from a file, its atom and bond chirality are not automatically perceived, the user has to call OEPerceiveChiral explicitly.

Atom Stereochemistry

Stereochemistry around atoms can be set and retrieved by the OEAtomBase.SetStereo and OEAtomBase.GetStereo methods, respectively. The OEAtomBase.HasStereoSpecified method returns a boolean value that indicates whether stereochemical information of a particular type has been stored for an atom. OEChem TK currently only supports OEAtomStereo.Tetrahedral atom stereochemistry class.

Note that the setting and retrieval of atom stereo requires a vector containing pointers to the neighboring atoms as the first argument. The handedness value returned from OEAtomBase.GetStereo will depend on the order of the neighboring atoms as they appear in the passed vector.

The first neighbor atom in the vector passed to OEAtomBase.GetStereo is taken as atom number one for the determination of handedness. Likewise, subsequent atoms in the neighbor atom vector are assigned sequentially to positions in the handedness definition. Although, three neighboring atoms are sufficient to determine the handedness around a trigonal pyramidal or tetrahedral center, either three or four atoms can be provided to the OEAtomBase.GetStereo function when requesting a value for tetrahedral chirality. The following table shows the return values of OEAtomBase.GetStereo method by passing the neighbor atoms in different order.

neighbor order [C@@H](Cl)(Br)N [C@H](Cl)(Br)N
H Cl Br N right handed left handed
H Br Cl N left handed right handed
H Cl N Br left handed right handed
... ... ...
Cl Br N left handed right handed
Br Cl N right handed left handed
Cl N Br right handed left handed

Note

The definition of handedness for tetrahedral stereochemistry does not imply chirality around a tetrahedral center, but rather indicates relative positions of neighboring atoms.

The following code sample demonstrates looping over atoms, testing for atoms that have tetrahedral stereochemistry, and printing out the value of the tetrahedral stereochemistry (either OEAtomStereo.RightHanded, OEAtomStereo.LeftHanded, or OEAtomStereo.Undefined). See also the input structure depicted in Figure: Atom stereo.

Listing 1: Accessing atom stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class PrintAtomStereo {

    public static void main(String argv[]) {
        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol, "[H][C@]1(NC[C@@H](CC1CO[C@H]2CC[C@@H](CC2)O)N)[H]");

        for (OEAtomBase atom : mol.GetAtoms()) {
            boolean chiral = atom.IsChiral();
            int stereo = OEAtomStereo.Undefined;
            if (atom.HasStereoSpecified(OEAtomStereo.Tetrahedral)) {
                OEAtomBaseVector v = new OEAtomBaseVector();
                for (OEAtomBase nbr : atom.GetAtoms()) {
                    v.add(nbr);
                }
                stereo = atom.GetStereo(v, OEAtomStereo.Tetrahedral);
            }
            if (chiral || stereo != OEAtomStereo.Undefined) {
                System.out.print("Atom: " + atom.GetIdx() + " chiral= " + chiral + " stereo= ");
                if (stereo == OEAtomStereo.RightHanded) {
                    System.out.println("right handed");
                } else if (stereo == OEAtomStereo.LeftHanded) {
                    System.out.println("left handed");
                } else {
                    System.out.println("undefined");
                }
            }
        }
    }
}

The output of the preceding program is the following:

Atom: 1 chiral=false stereo=left handed
Atom: 4 chiral=true stereo=right handed
Atom: 7 chiral=true stereo=undefined
Atom: 10 chiral=false stereo=left handed
Atom: 14 chiral=false stereo=right handed
../_images/AtomStereo.png

Atom stereo

As mentioned before, tetrahedral stereochemistry (i.e. specified atom stereo) does not imply chirality around a tetrahedral center. For example atoms 1, 10 and 14 in Figure: Atom stereo have specified atom stereo, even though they are non-chiral. Vice versa, atom can be chiral but with unspecified atom stereo configuration (such as atom 7 in Figure: Atom stereo ). Atoms 1 and 6 are non-chiral but they have atom stereo information and they are relative to each other.

The following example shows how to manually set the atom stereo of atom 7 (chiral, undefined) to left by the OEAtomBase.SetStereo method.

Listing 2: Setting atom stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class SetAtomStereo {

    public static void main(String argv[]) {
        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol,"[H][C@]1(NC[C@@H](CC1CO[C@H]2CC[C@@H](CC2)O)N)[H]");

        for (OEAtomBase atom : mol.GetAtoms()) {
            if (atom.IsChiral() && ! atom.HasStereoSpecified(OEAtomStereo.Tetrahedral)) {
                OEAtomBaseVector v = new OEAtomBaseVector();
                for (OEAtomBase neigh : atom.GetAtoms()) {
                    v.add(neigh);
                }
                atom.SetStereo(v,OEAtomStereo.Tetra,OEAtomStereo.Left);
            }
        }
        System.out.println(oechem.OEMolToSmiles(mol));
    }
}

The output of the preceding program is the following:

[H][C@@]1([C@@H](C[C@H](CN1)N)CO[C@H]2CC[C@@H](CC2)O)[H]

Just as in OEAtomBase.GetStereo, the vector of neighbor atoms provide the references about which the handedness is defined. The first of the integer arguments is the stereochemistry type (i.e. OEAtomStereo.Tetrahedral (or just OEAtomStereo.Tetra) , and the second is the associated value (i.e. OEAtomStereo.Right or OEAtomStereo.Left).

Bond Chirality

The following two code snippets demonstrate how to loop over chiral bonds using the OEIsChiralBond functor and the IsChiral method of the OEBondBase class.

for (OEBondBase bond : mol.GetBonds(new OEIsChiralBond())) {
    System.out.println(bond.GetBgnIdx() + "=" + bond.GetEndIdx());
}
for (OEBondBase bond : mol.GetBonds()) {
    if (bond.IsChiral()) {
        System.out.println(bond.GetBgnIdx() + "=" + bond.GetEndIdx());
    }
}

Warning

When a molecule is imported from a file, its atom and bond chirality are not automatically perceived, the user has to call OEPerceiveChiral explicitly.

Bond Stereochemistry

Stereochemistry around bonds can be specified in a similar fashion to stereochemistry about atom centers. The request for stereochemistry of a particular class can be made of an OEBondBase using the method OEBondBase.HasStereoSpecified. OEChem TK currently only supports OEBondStereo.CisTrans bond stereochemistry class that defines whether the configuration of two atoms around a non-rotatable bond is cis or trans. If a bond has associated stereochemical data, it can be retrieved using OEBondBase.GetStereo method.

The following code sample demonstrates a loop over bonds that tests for bonds with associated stereochemistry, and retrieval of whether the neighboring atoms are cis or trans relative to one another. (See also the input structure depicted in Figure: Bond stereo.

Listing 3: Accessing bond stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class PrintBondStereo {

    public static void main(String argv[]) {

        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol, "C\\C=C\\C=C/C=CC");

        for (OEBondBase bond : mol.GetBonds()) {
            if (bond.HasStereoSpecified(OEBondStereo.CisTrans)) {
                for (OEAtomBase atom1 : bond.GetBgn().GetAtoms()) {
                    if (atom1.GetIdx() == bond.GetEnd().GetIdx()) {
                        continue;
                    }
                    for (OEAtomBase atom2 : bond.GetEnd().GetAtoms()) {
                        if (atom2.GetIdx() == bond.GetBgn().GetIdx()) {
                            continue;
                        }
                        OEAtomBaseVector v = new OEAtomBaseVector();
                        v.add(atom1);
                        v.add(atom2);
                        int stereo =  bond.GetStereo(v,OEBondStereo.CisTrans);
                        System.out.print("Atoms: " + atom1.GetIdx() + " and " + atom2.GetIdx() + " are ");
                        if (stereo == OEBondStereo.Cis) {
                            System.out.println("cis");
                        } else if (stereo == OEBondStereo.Trans) {
                            System.out.println("trans");
                        }
                    }
                }
            }
        }
    }
}

The output of the preceding program is the following:

Atoms: 0 and 3 are trans
Atoms: 2 and 5 are cis
../_images/BondStereo.png

Bond stereo

Note that even though the double bond defined by atoms 4–5–6–7 is depicted as trans (see Figure: Bond stereo) it is still considered undefined, since no stereo information is encoded for this bond in the input SMILES.

The following example shows how to manually set this missing bond stereo to trans by the OEBondBase.SetStereo method.

Listing 4: Setting bond stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class SetBondStereo {

    public static void main(String argv[]) {
        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol, "C\\C=C\\C=C/C=CC");

        for (OEBondBase bond : mol.GetBonds()) {
            if (bond.GetOrder() == 2 && !bond.HasStereoSpecified(OEBondStereo.CisTrans)) {
                OEAtomBaseVector v = new OEAtomBaseVector();
                for (OEAtomBase neigh : bond.GetBgn().GetAtoms()) {
                    if (neigh.GetIdx() != bond.GetEnd().GetIdx()) {
                        v.add(neigh);
                        break;
                    }
                }
                for (OEAtomBase neigh : bond.GetEnd().GetAtoms()) {
                    if (neigh.GetIdx() != bond.GetBgn().GetIdx()) {
                        v.add(neigh);
                        break;
                    }
                }
                bond.SetStereo(v,OEBondStereo.CisTrans,OEBondStereo.Trans);
            }
        }
        System.out.println(oechem.OEMolToSmiles(mol));
    }
}

The first integer argument of the method OEBondBase.SetStereo is used to specify the type of stereochemistry (i.e. OEBondStereo.CisTrans). The second integer argument specifies the bond stereo configuration (i.e. OEBondStereo.Cis or OEBondStereo.Trans)

The output of the preceding program is the following:

C/C=C/C=C\C=C\C

CIP Stereo Perception

The following two examples demonstrate how to perceive CIP (Cahn–Ingold–Prelog) atom and bond stereo information.

../_images/CIPAtomStereo.png

CIP atom stereo

Listing 5: Perceiving CIP atom stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class PrintCIPAtomStereo {

    public static void main(String argv[]) {

        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol, "N[C@@H]1N[C@@H](O)CC(O)C1.C2[C@@H](O)CC[C@@H](O)C2");

        for (OEAtomBase atom : mol.GetAtoms()) {

            int cip = oechem.OEPerceiveCIPStereo(mol,atom);

            if (atom.HasStereoSpecified()) {
                System.out.print("atom " + atom.GetIdx() + " is ");

                if (cip == OECIPAtomStereo.S) {
                    System.out.println("S");
                } else if (cip == OECIPAtomStereo.R) {
                    System.out.println("R");
                } else if (cip == OECIPAtomStereo.NotStereo) {
                    System.out.println("not a CIP stereo center");
                }

            } 
            if (cip == OECIPAtomStereo.UnspecStereo) {
                System.out.print("atom " + atom.GetIdx() + " is ");
                System.out.println("a CIP stereo center without specified stereochemistry");
            }
        }
    }
}

The OEPerceiveCIPStereo function detects the Cahn-Ingold-Prelog descriptor of the given atom and returns a value from the OECIPAtomStereo namespace.

The output of Listing 5 is the following: (See also the input structure depicted in Figure: CIP atom stereo.

atom 1 is R
atom 4 is S
atom 8 is a CIP stereo center without specified stereochemistry
atom 12 is not a CIP stereo center
atom 17 is not a CIP stereo center
../_images/CIPBondStereo.png

CIP bond stereo

Listing 6: Perceiving CIP bond stereo information

package openeye.docexamples.oechem;

import openeye.oechem.*;

public class PrintCIPBondStereo {

    public static void main(String argv[]) {

        OEGraphMol mol = new OEGraphMol();
        oechem.OESmilesToMol(mol, "C\\C(C)=C(\\C)C.O\\C(C)=C(\\C)O.O\\C(C)=C(\\O)C.CC(O)=C(O)C");

        for (OEBondBase bond : mol.GetBonds()) {
            if (bond.GetOrder() == 2) {

                int cip = oechem.OEPerceiveCIPStereo(mol,bond);

                System.out.print("bond " + bond.GetIdx() + " is ");
                if (bond.HasStereoSpecified()) {

                    if (cip == OECIPBondStereo.E) {
                        System.out.println("E");
                    } else if (cip == OECIPBondStereo.Z) {
                        System.out.println("Z");
                    } else if (cip == OECIPBondStereo.NotStereo) {
                        System.out.println("not a CIP stereo center");
                    }

                } 
                if (cip == OECIPBondStereo.UnspecStereo) {
                    System.out.println("a CIP stereo center without specified stereochemistry");
                }
            }
        }
    }
}

The OEPerceiveCIPStereo function detects the Cahn-Ingold-Prelog descriptor of the given bond and returns a value from the OECIPBondStereo namespace.

The output of Listing 6 is the following: (See also the input structure depicted in Figure: CIP bond stereo.

bond 2 is not a CIP stereo center
bond 7 is Z
bond 12 is E
bond 17 is a CIP stereo center without specified stereochemistry