Drawing a Ligand-Protein Complex Surface

The previous chapter demonstrates how to draw and customize 2D molecule surfaces. Grapheme TK also provides a method that depicts a ligand-protein complex in which the arcs of the 2D surface of the molecule are annotated based on the distance between the accessible surfaces of the ligand and the surrounding protein (OEMakeAccessibleSurface). Based on this calculation, the atoms of the ligand are divided into four categories which are then inherited by the corresponding arcs when the 2D molecule surface of the ligand is drawn. These four types are the following:

  1. Solvent (OEDefaultSolventArcFxn)

    A surface arc is depicted using the solvent style if the corresponding atom is accessible to a solvent. (See Figure: Example of the ‘solvent’ arc style)

    ../_images/OEDefaultSolventArcFxn.png

    Example of the ‘solvent’ arc style

  2. Cavity (OEDefaultCavityArcFxn)

    A surface arc is depicted using the cavity style if in the region of the corresponding atom, a cavity is detected between the ligand and the receptor molecule surfaces. The cavity is large enough to allow expanding the ligand in this region without bumping into the receptor. (See Figure: Example of the cavity arc style)

    ../_images/OEDefaultCavityArcFxn.png

    Example of the ‘cavity’ arc style

  3. Void (OEDefaultVoidArcFxn)

    A surface arc is depicted using the void style, if in the region of the corresponding atom a small interstice is detected between the ligand and the receptor molecule surfaces. (See Figure: OEDefaultBuriedArcFxn)

    ../_images/OEDefaultVoidArcFxn.png

    Example of the ‘void’ arc style

  4. Buried (OEDefaultBuriedArcFxn)

    A surface arc is depicted using the buried style, if in the region of the corresponding atom the ligand is tightly fit to the receptor. (See Figure: Example of the buried arc style)

    ../_images/OEDefaultBuriedArcFxn.png

    Example of the ‘buried’ arc style

Note

Even though, Spicoli TK is used to generate the accessible surfaces of the ligand and the receptor, no Spicoli TK license is required to call the OEAddComplexSurfaceArcs function.

The following Listing 1 example show how to display the surface of the ligand-protein complex. After importing the ligand and the receptor structures, the OEAddComplexSurfaceArcs function is called to generate the accessible molecule surfaces (using Spicoli TK) and assign the surface drawing styles (solvent, buried, void, or cavity) for the atoms of the ligand. These styles are the used to draw the arcs of the molecule surface when the OEDraw2DSurface function is invoked. The OEGetMoleculeSurfaceScale function is used to reduce the scaling of the molecule in order to be able to fit both the molecule diagram and the molecule surface into the image.

Listing 1: Example of complex surface drawing

public class DrawComplexSurface
{
    public static OEGraphMol ImportMolecule (String filename)
    {
        oemolistream ifs = new oemolistream();
        OEGraphMol mol = new OEGraphMol();
        if (!ifs.open(filename))
        {
            OEChem.OEThrow.Fatal("Unable to open " + filename + " for reading");
        }

        if (!OEChem.OEReadMolecule(ifs, mol))
        {
            OEChem.OEThrow.Fatal("Unable to read molecule in " + filename);
        }

        OEChem.OEAssignBondiVdWRadii(mol);
        OEChem.OESuppressHydrogens(mol);

        return mol;
    }

    public static int Main(String[] args)
    {
        if (args.Length != 2)
        {
            OEChem.OEThrow.Usage("DrawComplexSurface <receptor> <ligand>");
        }

        OEGraphMol receptor = ImportMolecule(args[0]);

        OEGraphMol ligand = ImportMolecule(args[1]);

        uint width  = 450;
        uint height = 350;

        OEGrapheme.OEAddComplexSurfaceArcs(ligand, receptor);

        OEGrapheme.OEPrepareDepictionFrom3D(ligand);
        OE2DMolDisplayOptions opts = new OE2DMolDisplayOptions(width, height, OEScale.AutoScale);
        opts.SetScale(OEGrapheme.OEGetMoleculeSurfaceScale(ligand, opts));

        OE2DMolDisplay disp = new OE2DMolDisplay(ligand, opts);
        OEGrapheme.OEDraw2DSurface(disp);

        OEDepict.OERenderMolecule("DrawComplexSurface.png", disp);
        return 0;
    }
}

The following snapshot (Figure: Dihydrofolate reductase) displays the ligand of the 2w3a PDB complex in VIDA with the accessible surface of the protein. The image shown in the Figure: The Grapheme representation of the 2w3a complex is created by Listing 1 code for the same ligand-protein complex.

../_images/DrawComplexSurface-VIDA.png

Dihydrofolate reductase complexed with trimethoprim in VIDA (PDB 2w3a)

../_images/DrawComplexSurface.png

The Grapheme representation of the 2w3a complex

User-defined solvent and buried surface drawing styles can be implemented by deriving from the OESurfaceArcFxnBase base class. Similarly, user-defined cavity and void surface drawing styles can be implemented by deriving from the OEComplexSurfaceArcFxnBase base class. This later abstract class also stores the relative distance calculated between the ligand and the receptor. The following code snippet shows how to use this depth to emphasize the volume of the cavity by adjusting the size of the spikes when drawing the surface arcs using the OEDrawSunSurfaceArc function.

    private static void DrawSurfaceArc(OEImageBase image, double depth, OESurfaceArc arc, OEPen pen)
    {
      double edgeAngle = 5.0;
      double patternAngle = 5.0;
      double minPatternWidthRatio = 0.05;
      double maxPatternWidthRatio = 0.10 * depth;
      uint patternDirection = OEPatternDirection.Outside;
      OEGrapheme.OEDrawSunSurfaceArc(image, arc.GetCenter(), arc.GetBgnAngle(), arc.GetEndAngle(),
                                     arc.GetRadius(), pen, edgeAngle,
                                     patternDirection, patternAngle,
                                     minPatternWidthRatio, maxPatternWidthRatio);
    }

    private class SolventArcFxn : OESurfaceArcFxnBase
    {
        public override bool Call(OEImageBase image, OESurfaceArc arc)
        {
            OEPen pen = new OEPen(OEChem.OELightGrey, OEChem.OELightGrey);
            pen.SetLineWidth(0.5);
            OEGrapheme.OEDrawDefaultSurfaceArc(image, arc.GetCenter(), arc.GetBgnAngle(),
                                           arc.GetEndAngle(), arc.GetRadius(), pen);
            return true;
        }
        public override OESurfaceArcFxnBase CreateCopy()
        {
            SolventArcFxn copy = new SolventArcFxn();
            copy.ReleaseOwnership();
            return copy;
        }
    }

    private class BuriedArcFxn : OESurfaceArcFxnBase
    {
        public override bool Call(OEImageBase image, OESurfaceArc arc)
        {
            OEPen pen = new OEPen(OEChem.OEGrey, OEChem.OEGrey);
            pen.SetLineWidth(2.0);
            OEGrapheme.OEDrawDefaultSurfaceArc(image, arc.GetCenter(), arc.GetBgnAngle(),
                                           arc.GetEndAngle(), arc.GetRadius(), pen);
            return true;
        }
        public override OESurfaceArcFxnBase CreateCopy()
        {
            BuriedArcFxn copy = new BuriedArcFxn();
            copy.ReleaseOwnership();
            return copy;
        }
    }

    private class CavityArcFxn : OEComplexSurfaceArcFxnBase
    {
        public CavityArcFxn() {}
        public CavityArcFxn(CavityArcFxn rhs) : base(rhs) {}
        public override bool Call(OEImageBase image, OESurfaceArc arc)
        {
            OEPen pen = new OEPen(OEChem.OEBlack, OEChem.OEBlack);
            pen.SetLineWidth(2.0);
            DrawSurfaceArc(image, GetDepth(), arc, pen);
            return true;
        }
        public override OEComplexSurfaceArcFxnBase CreateComplexCopy()
        {
            CavityArcFxn copy = new CavityArcFxn(this);
            copy.ReleaseOwnership();
            return copy;
        }
        public override OESurfaceArcFxnBase CreateCopy()
        {
            CavityArcFxn copy = new CavityArcFxn(this);
            copy.ReleaseOwnership();
            return copy;
        }      
    }

    private class VoidArcFxn : OEComplexSurfaceArcFxnBase
    {
        public VoidArcFxn() {}
        public VoidArcFxn(VoidArcFxn rhs) : base(rhs) {}
        public override bool Call(OEImageBase image, OESurfaceArc arc)
        {
            OEPen pen = new OEPen(OEChem.OEDarkGrey, OEChem.OEDarkGrey);
            pen.SetLineWidth(2.0);
            DrawSurfaceArc(image, GetDepth(), arc, pen);
            return true;
        }
        public override OEComplexSurfaceArcFxnBase CreateComplexCopy()
        {
            VoidArcFxn copy = new VoidArcFxn(this);
            copy.ReleaseOwnership();
            return copy;
        }
        public override OESurfaceArcFxnBase CreateCopy()
        {
            VoidArcFxn copy = new VoidArcFxn(this);
            copy.ReleaseOwnership();
            return copy;
        }
    }

These arc drawing predicates then can be used to draw the surface of the ligand-protein complex when calling the OEAddComplexSurfaceArcs function. The image created is shown in Figure: Example of user-defined surface drawing.

SolventArcFxn sfxn = new SolventArcFxn();
BuriedArcFxn  bfxn = new BuriedArcFxn();
CavityArcFxn  cfxn = new CavityArcFxn();
VoidArcFxn    vfxn = new VoidArcFxn();
OEGrapheme.OEAddComplexSurfaceArcsSpecial(ligand, receptor, sfxn, bfxn, cfxn, vfxn);
../_images/DrawComplexSurfaceUserDefined.png

Example of user-defined surface drawing

See also