Calculating Overlap

Overlap calculation is the simplest functionality offered through the Shape TK. These set of examples show how to calculate static overlap between two objects (molecules, grids or shape query). Note that static means that the two input species (ref and fit) are not moved at all. These examples simply calculate the overlap and/or other related quantities, given the input positions. Examples for performing calculations that actually optimize the alignment/overlap are considered in a separate section.

Simple Overlap

This example reads in a reference molecule and a few fit molecules and prints out the Exact overlap calculated.

Listing 1: Simple overlap using Exact Overlap

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("simpleoverlap <reffile> <fitfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Prepare reference molecule for calculation
  // With default options this will remove any explicit hydrogens present
  OEOverlapPrep prep;
  prep.Prep(refmol);

  // Get appropriate function to calculate exact shape
  OEExactShapeFunc shapeFunc;
  shapeFunc.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
    prep.Prep(fitmol);
    shapeFunc.Overlap(fitmol, res);
    oeout << fitmol.GetTitle();
    oeout << " exact tanimoto = " << res.GetTanimoto() << oeendl;
  }
  return 0;
}

Adding overlap to molecules

This next example program uses the Analytic overlap method and also uses a little extra OEChem to attach the overlap scores to each molecule as SD data. This can be used to rescore a set of ROCS hits or to measure the overlap of ROCS alignments against an exclusion region in the binding site.

Listing 2: Rescoring pre-aligned structures

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=4)
    OEThrow.Usage("rescore <reffile> <rocs_hits_file> <output.sdf>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Get appropriate function to calculate analytic shape
  OEAnalyticShapeFunc shapeFunc;
  shapeFunc.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
    shapeFunc.Overlap(fitmol, res);
    char buffer[12];
    sprintf(buffer, "%-6.3f", res.GetTanimoto()); 
    OESetSDData(fitmol, "AnalyticShapeTanimoto", buffer);
    OEWriteMolecule(outfs, fitmol);
  }
  return 0;
}

Color Overlap

This example reads in a reference molecule and a few fit molecules and prints out the Exact color score calculated. By default all color calculations are performed using the ImplicitMillsDean force field.

Listing 3: Calculating color score

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("coloroverlap <reffile> <fitfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Prepare reference molecule for calculation
  // With default options this will remove any explicit 
  // hydrogens present, and add required color atoms
  OEOverlapPrep prep;
  prep.Prep(refmol);

  // Get appropriate function to calculate exact color
  OEExactColorFunc colorFunc;
  colorFunc.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
      prep.Prep(fitmol);
      colorFunc.Overlap(fitmol, res);

      oeout << fitmol.GetTitle();
      oeout << " color score = " << res.GetColorScore() << oeendl;
  }
  return 0;
}

Adding color score to molecules

This next example uses the ImplicitMillsDean force field and the Analytic color to rescore a set of ROCS hits and add the color scores to SD tags.

Listing 4: Using color to add scores to pre-aligned molecules.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("colorscore <reffile> <overlayfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Prepare reference molecule for calculation
  // With default options this will add required color atoms 
  OEOverlapPrep prep;
  prep.Prep(refmol);

  // Get appropriate function to calculate analytic color
  OEAnalyticColorFunc colorFunc;
  colorFunc.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
      prep.Prep(fitmol);
      colorFunc.Overlap(fitmol, res);
      cout << "Fit Title: " << fitmol.GetTitle() << " ";
      cout << "Color Tanimoto: " << res.GetColorTanimoto() << endl;
  }
  return 0;
}

User Defined Color

As a step toward writing a complete color force field, it is possible to combine built-in rules for color atom assignment with user defined interactions. A new OEColorForceField object can be created using one of the built-in types, then the interactions can be cleared using OEColorForceField::ClearInteractions and subsequent user interactions added with OEColorForceField::AddInteraction.

For example, to use the ImplicitMillsDean atom typing rules, but to only consider donor-donor and acceptor-acceptor interactions, one can use the following:

Listing 5: Using ImplicitMillsDean with user interactions.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=4)
    OEThrow.Usage("usercolor <reffile> <rocs_hits_file> <output.sdf>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Modify ImplicitMillsDean color force field by
  // adding user defined color interactions
  OEColorForceField cff;
  cff.Init(OEColorFFType::ImplicitMillsDean);
  cff.ClearInteractions();
  unsigned int donorType = cff.GetType("donor");
  unsigned int accepType = cff.GetType("acceptor");
  cff.AddInteraction(donorType, donorType, "gaussian", -1.0, 1.0);
  cff.AddInteraction(accepType, accepType, "gaussian", -1.0, 1.0);

  // Prepare reference molecule for calculation
  // With default options this will add required color atoms
  // Set the modified color force field for addignment
  OEOverlapPrep prep;
  prep.SetColorForceField(cff);
  prep.Prep(refmol);
  
  // Get appropriate function to calculate exact color
  // Set appropriate options to use the user defined color
  OEColorOptions options;
  options.SetColorForceField(cff);
  OEExactColorFunc colorFunc(options);
  colorFunc.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
    prep.Prep(fitmol);
    colorFunc.Overlap(fitmol, res);
    oeout << fitmol.GetTitle();
    oeout << " Color tanimoto = " << res.GetColorTanimoto() << oeendl;
  }
  return 0;
}

Shape and Color Overlap

This example reads in a reference molecule and a few fit molecules and prints out both the shape overlap and the color score calculated. By default the OEOverlapFunc uses the Grid shape and Exact color.

Listing 6: Calculating both shape and color overlap

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("overlapcolor <reffile> <fitfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEGraphMol refmol;
  OEReadMolecule(reffs, refmol);

  // Prepare reference molecule for calculation
  // With default options this will remove any explicit hydrogens present
  OEOverlapPrep prep;
  prep.Prep(refmol);

  // Get appropriate function to calculate both shape and color
  // By default the OEOverlapFunc contains OEGridShapeFunc for shape 
  // and OEExactColorFunc for color
  OEOverlapFunc func;
  func.SetupRef(refmol);

  OEOverlapResults res;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
    prep.Prep(fitmol);
    func.Overlap(fitmol, res);
    oeout << fitmol.GetTitle();
    oeout << " tanimoto combo = " << res.GetTanimotoCombo() << oeendl;
    oeout << " shape tanimoto = " << res.GetTanimoto() << oeendl;
    oeout << " color tanimoto = " << res.GetColorTanimoto() << oeendl;
  }
  return 0;
}

ROCS

The high-level OEROCS provides the simplest way to maximize shape and/or color between two objects. OEROCS uses the same shape and color functions as used for static overlap calculation, but optimizes the overlap between the reference and the fit objects. By default both shape and color optimization is performed, with shape estimated the Grid method and color estimated with the Exact method.

The fit object is not moved during the optimization. Part of the results returned from the calculation are the transform required to move the fit object into the final orientation. The results also contain a copy of the fit molecule conformer(s) in its final orientation.

A helper function OEROCSOverlay is created for the most simple usage of the functionality that performs optimizations between a set of conformers and returns the best hit.

Best Hit

This example reads in a reference molecule and a fit molecule, performs overlay optimization, finds the best hit conformer and prints it out in final orientation.

Listing 7: Finding best hit conformer pair

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=4)
    OEThrow.Usage("besthit <reffile> <fitfile> <outfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);

  OEMol refmol;
  OEReadMolecule(reffs, refmol);

  OEMol fitmol;
  OEReadMolecule(fitfs, fitmol);

  OEROCSResult res;
  OEROCSOverlay(res, refmol, fitmol);
  OEGraphMol outmol = OEGraphMol(res.GetOverlayConf());

  OEWriteMolecule(outfs, outmol);
  oeout << "Tanimoto combo = " << res.GetTanimotoCombo() << oeendl;
  return 0;
}

Top Hits

This example reads in a reference molecule and a few fit molecules, performs overlay optimization, finds the few top hits, and prints them out in final orientation.

Listing 8: Finding top ROCS hits

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=5)
    OEThrow.Usage("tophits <reffile> <fitfile> <outfile> <nhits>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);
  unsigned int nhits = (unsigned int)atoi(argv[4]);

  OEMol refmol;
  OEReadMolecule(reffs, refmol);

  // Setup OEROCS with specified number of best hits
  OEROCSOptions options;
  options.SetNumBestHits(nhits);
  OEROCS rocs(options);
  rocs.SetDatabase(fitfs);

  OEIter<OEROCSResult> res = rocs.Overlay(refmol); 
  for (; res; ++res)
  {
    OEGraphMol outmol = OEGraphMol(res->GetOverlayConf());
    OEWriteMolecule(outfs, outmol);
    oeout << " title = " << outmol.GetTitle() << oeendl;
    oeout << " tanimoto combo = " << res->GetTanimotoCombo() << oeendl;
  }
  return 0;
}

Top Hits with Multiple Conformers

This example repeats the Top Hits example above but fixes the number of hits to 3 and asks for multiple best conformers for each hit reported.

Listing 9: Finding top ROCS hits with multiple conformers

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=5)
    OEThrow.Usage("tophitsconf <reffile> <fitfile> <outfile> <confsperhit>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);
  unsigned int nconfs = (unsigned int)atoi(argv[4]);

  OEMol refmol;
  OEReadMolecule(reffs, refmol);

  // Setup OEROCS with specified number of best hits
  OEROCSOptions options;
  options.SetNumBestHits(3);
  options.SetConfsPerHit(nconfs);
  OEROCS rocs(options);
  rocs.SetDatabase(fitfs);

  OEIter<OEROCSResult> res = rocs.Overlay(refmol); 
  for (; res; ++res)
  {
    OEMol outmol = OEMol(res->GetOverlayConfs());
    OEWriteMolecule(outfs, outmol);
    oeout << " title = " << outmol.GetTitle() << oeendl;
    oeout << " tanimoto combo = " << res->GetTanimotoCombo() << oeendl;
  }
  return 0;
}

Overlay Optimization

The OEOverlay and OEMultiRefOverlay, compared to OEROCS, allows setting up a reference system and process overlay optimization of multiple fit molecules. Another difference is that both OEOverlay and OEMultiRefOverlay, in addition to providing the best overlay score, also gives access to all the results obtained during a overlay optimization. Methods Overlay and Overlay, that provides all results should only be used when such rigorous amount of resulting data is desired.

Best Optimization Result

This example reads in a reference molecule and a few fit molecules, performs overlay optimization, and returns only the best result per reference to fit molecule overlay optimization.

Listing 10: Getting the best scores from OEMultiRefOverlay.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

// This example reads in a reference molecule and a few fit
// molecules, performs overlay optimization, sorts the results
// in tanimoto order, and shows the single best result.
// With the default options, OEOverlay optimizes both shape and color.

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("overlaybestres <reffile> <fitfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEMol refmol;
  OEReadMolecule(reffs, refmol);
  cout << "Ref Title: " << refmol.GetTitle() << " ";
  cout << "Num Confs: " << refmol.NumConfs() << endl << endl;

  // Prepare reference molecule for calculation
  // With default options this will remove any explicit 
  // hydrogens present and add color atoms
  OEOverlapPrep prep;
  prep.Prep(refmol);

  OEMultiRefOverlay overlay;
  overlay.SetupRef(refmol);

  OEMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
      prep.Prep(fitmol);
      OEBestOverlayScore score;
      overlay.BestOverlay(score, fitmol, OEHighestTanimoto());
      cout << "Fit Title: " << fitmol.GetTitle() << " ";
      cout << "FitConfIdx: " << score.GetFitConfIdx() << " ";
      cout << "RefConfIdx: " << score.GetRefConfIdx() << " ";
      cout << "Tanimoto: " << score.GetTanimoto() << endl; 
  }
  return 0;
}

All Optimization Results

This example repeats the above, but uses Overlay to obtain all the results.

A single Overlay calculation will return N results, where N is the number of ref conformers times the number of fit conformers times the number of starting positions for each pair. So comparing 2 molecules with 10 conformers each could return 400 or more results.

There are two helper classes designed solely to contain these results and to make it easy to extract all or just the desired subset. OEBestOverlayResults holds the results of a single pair of conformers. It contains a set of OEBestOverlayScore objects, one for each starting position.

This example uses 2 iterators to show all the results.

Listing 11: Getting all the scores from OEMultiRefOverlay.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

// This example reads in a reference molecule and a few fit
// molecules, performs overlay optimization, and uses 2 iterators to
// show all the results.
// With the default options, OEOverlay optimizes both shape and color.

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("overlayallres <reffile> <fitfile>");

  oemolistream reffs(argv[1]);
  oemolistream fitfs(argv[2]);

  OEMol refmol;
  OEReadMolecule(reffs, refmol);
  cout << "Ref Title: " << refmol.GetTitle() << " ";
  cout << "Num Confs: " << refmol.NumConfs() << endl << endl;

  // Prepare reference molecule for calculation
  // With default options this will remove any explicit 
  // hydrogens present and add color atoms
  OEOverlapPrep prep;
  prep.Prep(refmol);

  OEMultiRefOverlay overlay;
  overlay.SetupRef(refmol);

  OEMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
      cout << "Fit Title: " << fitmol.GetTitle() << " ";
      cout << "Num Confs: " << fitmol.NumConfs() << endl;
       
      prep.Prep(fitmol);
      unsigned int resCount = 0;       

      // double loop over results and scores to obtain all scores
      OEIter<OEBestOverlayResults> resiter = overlay.Overlay(fitmol);
      for (; resiter; ++resiter)
      {
          OEIter<OEBestOverlayScore> scoreiter = resiter->GetScores();
          for (; scoreiter; ++scoreiter)
          {
              OEBestOverlayScore* score = scoreiter;
              cout << "FitConfIdx: " << score->GetFitConfIdx() << " ";
              cout << "RefConfIdx: " << score->GetRefConfIdx() << " ";
              cout << "Tanimoto: " << score->GetTanimoto() << endl;
              ++resCount;
          }
      }
      cout << resCount << " results returned" << endl << endl;
  }
  return 0;
}

Manipulating all results

This example repeats the above to access all overlay results, and shows how to navigate through the results to extract a specific set. Here, the OESortOverlayScores function is used to turn the double iterator as shown in the example above into a single iterator of OEBestOverlayScore. Note that the third argument is a functor used to sort the list, such that in this next example, we get one OEBestOverlayScore for each pair of conformers and they are returned in Tanimoto order.

OEOverlay or OEMultiRefOverlay does not actually move the fit molecule. Part of OEBestOverlayScore is the rotation matrix and translation matrix necessary to move the fit molecule into the final overlap position. (N.B. the rotation matrix is left-multiplied so can be regarded as left-handed.) This example also shows how to apply these transformations. The OpenEye standard is rotation then translation, but as a convenience, OEBestOverlayScore has OEBestOverlayScore::Transform method that will apply the transforms in the proper order.

This example keeps the user specified number of scores, aligns each fit conformer to the ref conformer it was overlaid on, and then write the pair to an output file. If SD or OEB is used as the output file type, then scores will also be stored in SD tags.

Listing 12: Writing few aligned structures from OEMultiRefOverlay.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

// This example reads in a reference molecule and a few fit
// molecules, performs overlay optimization, sorts the results
// in tanimoto order, shows the user specified number of 
// results, and saves the overlayed structures.
// With the default options, OEOverlay optimizes both shape and color.

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
    if (argc!=5)
      OEThrow.Usage("overlaystruct <reffile> <fitfile> <output.sdf> <keepsize>");

    oemolistream reffs(argv[1]);
    oemolistream fitfs(argv[2]);
    oemolostream outfs(argv[3]);
    unsigned int keepsize = (unsigned int)atoi(argv[4]);

    OEMol refmol;
    OEReadMolecule(reffs, refmol);
    cout << "Ref Title: " << refmol.GetTitle() << " ";
    cout << "Num Confs: " << refmol.NumConfs() << endl << endl;

    // Prepare reference molecule for calculation
    // With default options this will remove any explicit 
    // hydrogens present and add color atoms
    OEOverlapPrep prep;
    prep.Prep(refmol);

    OEMultiRefOverlay overlay;
    overlay.SetupRef(refmol);

    OEMol fitmol;
    while (OEReadMolecule(fitfs, fitmol))
    {
        cout << "Fit Title: " << fitmol.GetTitle() << " ";
        cout << "Num Confs: " << fitmol.NumConfs() << endl;

        prep.Prep(fitmol);
        unsigned int resCount=0;
      
        OEIter<OEBestOverlayResults> resiter = overlay.Overlay(fitmol);

        // Sort all scores according to highest tanimoto
        OEIter<OEBestOverlayScore> scoreiter;
        OESortOverlayScores(scoreiter, resiter, OEHighestTanimoto());

        for (;scoreiter;++scoreiter)
        {
            OEBestOverlayScore* score = scoreiter;
            OEGraphMol outmol(*fitmol.GetConf(OEHasConfIdx(score->GetFitConfIdx())));
            score->Transform(outmol);

            char buffer[12];
            sprintf(buffer, "%-d", score->GetRefConfIdx());
            OESetSDData(outmol, "RefConfIdx", buffer);
            sprintf(buffer, "%-6.3f", score->GetTanimotoCombo());
            OESetSDData(outmol, "TanimotoCombo", buffer);

            OEWriteMolecule(outfs, *refmol.GetConf(OEHasConfIdx(score->GetRefConfIdx())));
            OEWriteMolecule(outfs, outmol);

            ++resCount;

            // Break at the user specified size
            if (resCount==keepsize)
                break;
        }
        cout << resCount << " results returned" << endl << endl;
    }
  return 0;
}

Working with Shape Query

This section of examples shows the use of a OEShapeQuery, and performs calculations where a shape query is used a the reference system instead of a molecule as the reference.

Creating a shape query

This examples shows how to create a simple shape query that combines a molecule with gaussians. In this example, the molecule is added in the query to define shape, and color is added separately in terms to gaussians. The created query is then saved in a file.

Listing 13: Creating a shape query.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("createquery <molfile> <outfile>");

  oemolistream molfs(argv[1]);
  OEGraphMol mol;
  OEReadMolecule(molfs, mol);

  // Use OEOverlapPrep to remove hydrogens and add 
  // color atoms to the molecule
  OEOverlapPrep prep;
  prep.Prep(mol);

  // Get the color atoms, create gaussians and add them
  // to the shape query
  OEShapeQuery query;
  OEIter<OEAtomBase> atom = OEGetColorAtoms(mol);
  for (; atom; ++atom)
  {
    float coords[3];
    mol.GetCoords(atom, coords);
    OEGaussian gauss(1.0f, 1.0f, coords, OEGetColorType(atom));
    query.AddColorGaussian(gauss);
  }

  // Remove color atoms from the molecule and add to the query
  OERemoveColorAtoms(mol);
  query.SetMolecule(mol);

  OEWriteShapeQuery(argv[1], query);
  oeout << "shape query created" << oeendl;
  return 0;
}

Overlap with shape query

This example reads in a reference shape query and a few fit molecules and prints out both the shape overlap and the color score calculated. By default the OEOverlapFunc uses the Grid shape and Exact color.

Listing 14: Overlap with a shape query

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("overlapquery <queryfile> <fitfile>");

  OEShapeQuery query;
  OEReadShapeQuery(argv[0], query);

  // Get appropriate function to calculate both shape and color
  // By default the OEOverlapFunc contains OEGridShapeFunc for shape 
  // and OEExactColorFunc for color
  OEOverlapFunc func;
  func.SetupRef(query);

  OEOverlapResults res;
  oemolistream fitfs(argv[2]);
  OEOverlapPrep prep;
  OEGraphMol fitmol;
  while (OEReadMolecule(fitfs, fitmol))
  {
    prep.Prep(fitmol);
    func.Overlap(fitmol, res);
    oeout << fitmol.GetTitle();
    oeout << " tanimoto combo = " << res.GetTanimotoCombo() << oeendl;
    oeout << " shape tanimoto = " << res.GetTanimoto() << oeendl;
    oeout << " color tanimoto = " << res.GetColorTanimoto() << oeendl;
  }
  return 0;
}

Top hit against shape query

This example reads in a reference query and a few fit molecules, performs overlay optimization, finds the few top hits, and prints them out in final orientation.

Listing 15: Finding top ROCS hits against a query

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;


int main(int argc,char *argv[])
{
  if (argc!=5)
    OEThrow.Usage("tophitsquery <reffile> <fitfile> <outfile> <nhits>");

  oemolistream fitfs(argv[2]);
  oemolostream outfs(argv[3]);
  unsigned int nhits = (unsigned int)atoi(argv[4]);

  OEShapeQuery query;
  OEReadShapeQuery(argv[1], query);

  // Setup OEROCS with specified number of best hits
  OEROCSOptions options;
  options.SetNumBestHits(nhits);
  OEROCS rocs(options);
  rocs.SetDatabase(fitfs);

  OEIter<OEROCSResult> res = rocs.Overlay(query); 
  for (; res; ++res)
  {
    OEGraphMol outmol = OEGraphMol(res->GetOverlayConf());
    OEWriteMolecule(outfs, outmol);
    oeout << " title = " << outmol.GetTitle() << oeendl;
    oeout << " tanimoto combo = " << res->GetTanimotoCombo() << oeendl;
  }
  return 0;
}

Shape from Hermite expansion

Using Hermite expansion we can obtain two functionalities: expand a molecule into Hermite representation and compare two molecules that are in the Hermite representation by computing their shape-Tanimoto coefficient. We illustrate both functionalities below with two examples.

Hermite expansion

In this example we input a molecule, set the level of Hermite expansion using NPolyMax variable, determine the optimal parameters for \(\lambda_x, \lambda_y, \lambda_z\), and perform the computation of the Hermite expansion. At the end we output the resulting Hermite representation of the molecule as a grid, using CreateGrid method of the OEHermite class. The user can vary NPolyMax from low numbers, like 4 or 5, to higher numbers like 10-30 and observe convergence of the shape. Which value to use in practice depends on the size of the input molecule. Input molecule can be drug-like as well as a protein.

Listing 16: Expanding a molecular shape into Hermite polynomials

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include <openeye.h>

#include <oeshape.h>

#include "hermite-expansion.itf"

using namespace std;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;

int main(int argc,char *argv[])
{
  OEInterface itf(InterfaceData, argc, argv);
  
  const unsigned int NPolyMax = oeCast(unsigned int, itf.Get<int>("-NPolyMax"));
  const float gridspacing = itf.Get<float>("-gridspacing");

  const string ifname = itf.Get<string>("-inputfile");
  const string ofname = itf.Get<string>("-outputgrid");

  oemolistream ifs;
  if (!ifs.open(ifname))
    OEThrow.Fatal("Unable to open %s for reading", ifname.c_str());

  const string ext = OEFileExtension(ofname, "");
  if (ext != "grd")
    OEThrow.Fatal("Output grid file extension hast to be '.grd' ");

  OEMol mol;
  if (!OEReadMolecule(ifs, mol))
    OEThrow.Fatal("Unable to read molecule in %s", ifname.c_str());

  OESuppressHydrogens(mol);
  
  OEHermiteOptions hermiteoptions;
  hermiteoptions.SetNPolyMax(NPolyMax);
  hermiteoptions.SetUseOptimalLambdas(true);
   
  OEHermite hermite(hermiteoptions);

  if (!hermite.Setup(mol))
    OEThrow.Fatal("Was not able to Setup the molecule for the OEHermite class.");

  const OEHermiteOptions& hopts = hermite.GetOptions();

  cout << "Best lambdas found";
  cout << " X=" << hopts.GetLambdaX();
  cout << " Y=" << hopts.GetLambdaY();
  cout << " Z=" << hopts.GetLambdaZ() << endl;
  cout << "Hermite self-overlap = " << hermite.GetSelfOverlap() << endl;

  const vector<double>& coeffs = hermite.GetCoefficients();
  cout << "Hermite coefficients f_{l,m,n} in the following order l = 0..."<<NPolyMax
       << ", m = 0..."<<NPolyMax<<"-l, n = "<<NPolyMax<<"-l-m :"<<endl;
  for (size_t i = 0; i < coeffs.size(); ++i)
    cout << coeffs[i]<<" ";
  cout << endl;

  OEScalarGrid grid;
  hermite.CreateGrid(grid, gridspacing);

  if (!OEWriteGrid(ofname, grid))
    OEThrow.Fatal("Unable to write grid file");

  return 0;
}

Hermite Tanimoto comparison of shape

In the second example below we setup two molecules and compute the Tanimoto-shape similarity coefficient, using Hermite expansion. The Hermite prep parameter NPolyMax_MAX is used to vary NPolyMax parameter and compute the shape-Tanimoto coefficient. First molecule in the reference input file is used versus all molecules in the fit input file. Results are attached as SD data to the moved fit molecule, as dictated by Hermite overlay, and sent to the output file. One can observe convergence of the Hermite Tanimoto coefficients as the level of expansion becomes more accurate.

Listing 17: Calculating shape Tanimoto using Hermite expansion

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include <openeye.h>

#include <oeshape.h>

#include "hermite-tanimoto.itf"

using namespace std;
using namespace OESystem;
using namespace OEChem;
using namespace OEOpt;
using namespace OEShape;

void CreateRMat(double alpha, double beta, double gamma, double * rmat)//standard matrix for rotation 
  {
    rmat[0]=cos(beta)*cos(gamma);
    rmat[1]=cos(gamma)*sin(alpha)*sin(beta)-cos(alpha)*sin(gamma);
    rmat[2]=cos(alpha)*cos(gamma)*sin(beta)+sin(alpha)*sin(gamma);
    rmat[3]=cos(beta)*sin(gamma);
    rmat[4]=cos(alpha)*cos(gamma)+sin(alpha)*sin(beta)*sin(gamma);
    rmat[5]=-cos(gamma)*sin(alpha)+cos(alpha)*sin(beta)*sin(gamma);
    rmat[6]=-sin(beta);
    rmat[7]=cos(beta)*sin(alpha);
    rmat[8]=cos(alpha)*cos(beta);
  }

OEMol GetInertialRmatTransInverse(const OEMol & mol, const OEMol & final_mol)
{

  OESystem::OEOwnedPtr<OEChem::OEMCMolBase> copy_mol(OENewMCMolBase(mol, OEChem::OEMCMolType::DoubleCartesian));  
  OESystem::OEOwnedPtr<OEChem::OEMCMolBase> copy_mol_2(OENewMCMolBase(final_mol, OEChem::OEMCMolType::DoubleCartesian));  
  
  OEChem::OETrans transfm;
  OEOrientByMomentsOfInertia(*copy_mol, transfm);

  transfm.Transform(copy_mol_2);

  return *copy_mol_2;

}

OEMol GetInertialRmatTransDirect(const OEMol & mol)
{

  OESystem::OEOwnedPtr<OEChem::OEMCMolBase> copy_mol(OENewMCMolBase(mol, OEChem::OEMCMolType::DoubleCartesian));
  OEChem::OETrans transfm;
  OEGetMomentsOfInertiaTransform(transfm, *copy_mol);

  transfm.Transform(copy_mol);

  return *copy_mol;
}


OEMol GetOptTransform(const OEMol & refmol, const OEMol & fitmol, double *xopt)
{

  double ropt[9];
  double topt[3];

  for (unsigned int i = 0; i < 3; ++i)
    topt[i] = xopt[i];

  CreateRMat(xopt[3], xopt[4], xopt[5], ropt);

  OEMol refmol_copy(refmol);
  OEMol fitmol_copy(fitmol);


  OEMol fitmol_moved(GetInertialRmatTransDirect(fitmol));

    
  OERotate(fitmol_moved, ropt);
  OETranslate(fitmol_moved, topt);    


  OEMol fitmol_moved_final(GetInertialRmatTransInverse(refmol_copy, fitmol_moved));

  return fitmol_moved_final;

}



int main(int argc,char *argv[])
{
  OEInterface itf(InterfaceData, argc, argv);
  
  const unsigned int NPolyMax_MAX = oeCast(unsigned int, itf.Get<int>("-NPolyMax_MAX"));

  const string ifrefname = itf.Get<string>("-inputreffile");
  const string iffitname = itf.Get<string>("-inputfitfile");
  const string ofname = itf.Get<string>("-outputfile");

  oemolistream ifsref;
  oemolistream ifsfit;
  oemolostream ofs;

  if (!ifsref.open(ifrefname))
    OEThrow.Fatal("Unable to open %s for reading", ifrefname.c_str());

  if (!ifsfit.open(iffitname))
    OEThrow.Fatal("Unable to open %s for reading", iffitname.c_str());
  
  OEMol refmol;
  OEMol fitmol;

  OENewtonOpt newtonopt;
  newtonopt.SetTolerance(0.0001);
  newtonopt.SetIterLimit(200);

  if (!OEReadMolecule(ifsref, refmol))
    OEThrow.Fatal("Unable to read molecule in %s", ifrefname.c_str());

  OESuppressHydrogens(refmol);

  if (!ofs.open(ofname))
    OEThrow.Fatal("Unable to open %s for writing", ofname.c_str());
  OEWriteMolecule(ofs, refmol);

  unsigned int idx = 0;
  while (OEReadMolecule(ifsfit, fitmol))
  {
    OESuppressHydrogens(fitmol);

    OESystem::OEOwnedPtr<OEChem::OEMCMolBase> copy_fitmol(OENewMCMolBase(fitmol, OEChem::OEMCMolType::DoubleCartesian));  

    cout<<"Working on the fit molecule with idx = "<< idx <<"..." << endl;
      
    OEBestOverlay best;
    best.SetRefMol(refmol);
    
    OEIter<OEBestOverlayResults> resiter = best.Overlay(fitmol);
    cout<<"ROCS Taniomoto list= { ";
    for (;resiter;++resiter)
    {
      OEIter<OEBestOverlayScore> scoreiter = resiter->GetScores();
      for (;scoreiter;++scoreiter)
      cout<<scoreiter->tanimoto<<" ";
    }
    cout<<"}"<<endl;

    for (unsigned int i = 0; i < NPolyMax_MAX+1; ++i)
    {
      cout<<"Working on NPolyMax = "<<i<<endl;
      OEHermiteOptions hermiteoptionsref;
      hermiteoptionsref.SetNPolyMax(i);
      hermiteoptionsref.SetUseOptimalLambdas(true);

      OEHermite hermiteref(hermiteoptionsref);
      if (!hermiteref.Setup(refmol))
        OEThrow.Fatal("Was not able to Setup the reference molecule for the OEHermite class.");
    
      OEHermiteOptions hermiteoptionsfit;
      hermiteoptionsfit.SetNPolyMax(i);
      hermiteoptionsfit.SetUseOptimalLambdas(true);

      OEHermite hermitefit(hermiteoptionsfit);
      if (!hermitefit.Setup(*copy_fitmol))
        OEThrow.Fatal("Was not able to Setup the fit molecule for the OEHermite class.");
    
      double refvol = hermiteref.GetSelfOverlap(); 
      double fitvol = hermitefit.GetSelfOverlap();

      const OEHermiteOptions& hrefopts = hermiteref.GetOptions();
      const OEHermiteOptions& hfitopts = hermitefit.GetOptions();

      OEHermiteShapeFunc hermiteshapeoverlap(hrefopts, hfitopts);
      if (!hermiteshapeoverlap.SetupRef(refmol))
        OEThrow.Fatal("Was not able to Setup the reference molecule for the OEHermiteShapeFunc class.");

      if (!hermiteshapeoverlap.Setup(*copy_fitmol))
        OEThrow.Fatal("Was not able to Setup the fit molecule for the OEHermiteShapeFunc class.");

      double x[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
      double xOpt[6];
      OECheckpoint1* chk = 0;

      double bestoverlap = - newtonopt(hermiteshapeoverlap, chk, x, xOpt);

      double hermitetanimoto = bestoverlap/(refvol+fitvol-bestoverlap);

      cout<<"Hermite Tanimoto = "<<hermitetanimoto<<endl;
      
      stringstream tag;
      tag<<"HermiteTanimoto_" << i;
      stringstream tagvalue;
      tagvalue<<hermitetanimoto;

      OEMol fitmol_moved(GetOptTransform(refmol, *copy_fitmol, xOpt));

      OESetSDData(fitmol_moved, tag.str(), tagvalue.str());

      OEWriteMolecule(ofs, fitmol_moved);

    }
    idx++;
  }

  ofs.flush();
  ofs.close();


  if (idx==0)
    OEThrow.Warning("Fit molecules file does not contain valid molecules. The output file will be empty");
  
  cout << "Example finished ..."<<endl;
  return 0;
}

Advanced Examples

Calculating NxN scores

There are times when you want to have all the pairwise scores among a set of molecules. Maintaining this 2D matrix of scores is more complicated than the single set of scores from the ref vs. set of fit molecules examples shown above.

This example takes a set of molecules and performs all the pairwise shape optimizations with OEBestOverlay. It outputs a spreadsheet of the scores.

Listing 18: Calculating NxN scores.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

void oneConf(const OEConfBase &conf, OEOverlapPrep& prep, const char *filename, 
             oeofstream &csvfile)
{
  char buffer[8];
  csvfile << conf.GetTitle() << "_" << conf.GetIdx();
  OEGraphMol refmol(conf);

  OEOverlayOptions options;
  options.SetOverlapFunc(OEGridShapeFunc());
  OEOverlay overlay(options);
  overlay.SetupRef(refmol);

  oemolistream bfs(filename);
  OEMol fitmol;
  OEIter<OEBestOverlayScore> scoreiter;
  while (OEReadMolecule(bfs, fitmol))
  {
    prep.Prep(fitmol);
    OEIter<OEBestOverlayResults> resiter = overlay.Overlay(fitmol);
    OESortOverlayScores(scoreiter, resiter, OEHighestTanimoto(), 1, true);
    for (;scoreiter;++scoreiter)
    {
      sprintf(buffer, "%.2f", scoreiter->tanimoto);
      csvfile << "," << buffer;
    }
  }
  csvfile << oeendl;
}

void genHeader(const char *filename, oeofstream &csvfile)
{
  csvfile << "name";
  oemolistream ifs(filename);
  OEMol mol;
  while (OEReadMolecule(ifs, mol))
  {
    for (OEIter<OEConfBase> citer=mol.GetConfs();citer;++citer)
    {
      csvfile << "," << citer->GetTitle() << "_" << citer->GetIdx();
    }
  }
  csvfile << oeendl;
}

int main(int argc,char *argv[])
{
  if (argc!=3)
    OEThrow.Usage("nxnshape <infile> <file.csv>");

  oeofstream csvfile(argv[2]);
  genHeader(argv[1], csvfile);

  OEOverlapPrep prep;
  prep.SetAssignColor(false);
  oemolistream afs(argv[1]);
  OEMol molA;
  while (OEReadMolecule(afs, molA))
  {
    prep.Prep(molA);
    oeerr << molA.GetTitle() << oeendl;
    for (OEIter<OEConfBase> citer=molA.GetConfs();citer;++citer)
      oneConf(citer, prep, argv[1], csvfile);
  }
  return 0;
}

Calculating shape characteristics

While most functionality in the Shape Toolkit involves comparison of pairs of molecules, there are a few fundamental properties that can be calculated for a single molecule. All of these calculations are done using the same basic Gaussian description of a molecule as described above.

The simplest property to calculate is volume, using OECalcVolume.

In addition to simple volume calculations, the steric multipoles of a molecule can also be calculated. See section OECalcShapeMultipoles.

This next example demonstrates the calculation of volume and shape multipoles.

Listing 19: Calculating shape properties.

/*
(C) 2017 OpenEye Scientific Software Inc. All rights reserved.

TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
provided to current licensees or subscribers of OpenEye products or
SaaS offerings (each a "Customer").
Customer is hereby permitted to use, copy, and modify the Sample Code,
subject to these terms. OpenEye claims no rights to Customer's
modifications. Modification of Sample Code is at Customer's sole and
exclusive risk. Sample Code may require Customer to have a then
current license or subscription to the applicable OpenEye offering.
THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
liable for any damages or liability in connection with the Sample Code
or its use.
*/

#include "openeye.h"

#include "oeplatform.h"
#include "oesystem.h"
#include "oechem.h"
#include "oeshape.h"

using namespace OEPlatform;
using namespace OESystem;
using namespace OEChem;
using namespace OEShape;
using namespace std;

int main(int argc,char *argv[])
{
  if (argc!=2)
    OEThrow.Usage("shapeprops <infile>");

  oemolistream ifs(argv[1]);

  OEGraphMol mol;
  while (OEReadMolecule(ifs, mol))
  {
    OEThrow.Info("              Title: %s", mol.GetTitle());
    OEThrow.Info("             Volume: %8.2f", OECalcVolume(mol));
    OEThrow.Info("Volume: (without H): %8.2f", OECalcVolume(mol, false));

    float smult[14];
    OECalcShapeMultipoles(mol, smult);

    OEThrow.Info("  Steric multipoles:");
    OEThrow.Info("           monopole: %8.2f", smult[0]);
    OEThrow.Info("        quadrupoles: %8.2f %8.2f %8.2f", 
                 smult[1],smult[2],smult[3]);
    OEThrow.Info("          octopoles:");
    OEThrow.Info("                xxx: %8.2f  yyy: %8.2f  zzz: %8.2f",
                 smult[4],smult[5],smult[6]);
    OEThrow.Info("                xxy: %8.2f  xxz: %8.2f  yyx: %8.2f",
                 smult[7],smult[8],smult[9]);
    OEThrow.Info("                yyz: %8.2f  zzx: %8.2f  zzy: %8.2f",
                 smult[10],smult[11],smult[12]);
    OEThrow.Info("                xyz: %8.2f", smult[13]);

    OEThrow.Info("");

  }
  
  return 0;
}

Calculating excluded volume

This code demonstrates how to use the shape toolkit to do an overlay to a crystallographic ligand, then calculate the overlap of the database molecule to the cognate protein. The output includes a new score Rescore which is the ShapeTanimotoCombo penalized by the fraction overlap.

Command Line Interface

A description of the command line interface can be obtained by executing the program with the –help argument.

prompt> excludevolume --help

will generate the following output:

-q : Query file name
-e : Protein to use as exclusion volume
-d : Database file name
-o : Output file name

Code

Download code

excludevolume.cpp and excludevolume.txt interface file