OEBio Examples

Extracting the backbone of a protein

/**********************************************************************
  Copyright (C) 2006-2015 OpenEye Scientific Software, Inc.
***********************************************************************/
// This program demonstrates how to extract the backbone of a protein
#include <openeye.h>
#include <oesystem.h>
#include <oechem.h>
#include <oebio.h>

using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

static void BackBone(oemolistream& ifs, oemolostream& ofs)
{
  OEGraphMol mol;
  OEGraphMol backboneMol;
  OEIter<OEAtomBase> atom;
  static const bool adjustHCount = true;
  while (OEReadMolecule(ifs, mol))
  {
    if (!OEHasResidues(mol))
      OEPerceiveResidues(mol, OEPreserveResInfo::All);
    atom = mol.GetAtoms(OEIsBackboneAtom());
    OEIsAtomMember member(atom);

    OESubsetMol(backboneMol, mol, member, adjustHCount);
    OEWriteMolecule(ofs, backboneMol);
  }
}

int main(int argc, char *argv[])
{
  if (argc != 3)
    OEThrow.Usage("%s <inmol> <outmol>", argv[0]);

  oemolistream ifs;
  if (!ifs.open(argv[1]))
    OEThrow.Fatal("Unable to open %s for reading.", argv[1]);

  oemolostream ofs;
  if (!ofs.open(argv[2]))
    OEThrow.Fatal("Unable to open %s for writing.", argv[2]);

  BackBone(ifs, ofs);

  return 0;
}

See also

Splitting a Macro-molecular Complex

//**********************************************************************
//  Copyright (C) 2015 by OpenEye Scientific Software, Inc.
//***********************************************************************
// split the input molecule into components

#include <openeye.h>

#include <oechem.h>
#include <oebio.h>
#include "splitmolcomplex.itf"

using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

int main(int argc, char** argv)
{
  OEInterface itf(InterfaceData);
  OEConfigureSplitMolComplexOptions(itf);

  if(! OEParseCommandLine(itf, argc, argv))
    OEThrow.Fatal("Unable to interpret command line!");

  oemolistream ims;
  if (itf.Get<unsigned>("-modelnum") != 1u)
    ims.SetFlavor(OEFormat::PDB,
                  OEGetDefaultIFlavor(OEFormat::PDB) & ~OEIFlavor::PDB::ENDM);

  const std::string inputFile = itf.Get<std::string>("-in");
  if (! ims.open(inputFile))
    OEThrow.Fatal("Unable to open %s for reading", inputFile.c_str());

  OEGraphMol inmol;
  OEReadMolecule(ims, inmol);

  oemolostream oms;
  const std::string outFile = itf.Get<std::string>("-out");
  if (! oms.open(outFile))
    OEThrow.Fatal("Unable to open %s for writing", outFile.c_str());

  OESplitMolComplexOptions opts;
  OESetupSplitMolComplexOptions(opts, itf);

  if (itf.Get<bool>("-verbose"))
  { // don't bother counting sites unless we're going to print them
    const unsigned numSites = OECountMolComplexSites(inmol, opts);
    OEThrow.SetLevel(OEErrorLevel::Verbose);
    OEThrow.Verbose("sites %d", numSites);
  }

  OEGraphMol lig, prot, wat, other;

  if (! OESplitMolComplex(lig, prot, wat, other, inmol, opts))
    OEThrow.Fatal("Unable to split mol complex from %s", inputFile.c_str());

  if (lig.NumAtoms() != 0u)
  {
    OEThrow.Verbose("  lig %s", lig.GetTitle());
    OEWriteMolecule(oms, lig);
  }
  if (prot.NumAtoms() != 0u)
  {
    OEThrow.Verbose(" prot %s", prot.GetTitle());
    OEWriteMolecule(oms, prot);
  }
  if (wat.NumAtoms() != 0u)
  {
    OEThrow.Verbose("  wat %s", wat.GetTitle());
    OEWriteMolecule(oms, wat);
  }
  if (other.NumAtoms() != 0u)
  {
    OEThrow.Verbose("other %s", other.GetTitle());
    OEWriteMolecule(oms, other);
  }

  oms.close();

  return 0;
}

Splitting a Macro-molecular Complex Efficiently and Flexibly

//**********************************************************************
//  Copyright (C) 2016 by OpenEye Scientific Software, Inc.
//***********************************************************************
// split the input molecule into components using low-level api

#include <openeye.h>
#include <oesystem.h>
#include <oechem.h>
#include <oebio.h>

#include "splitmolcomplexlowlevel.itf"

#include <vector>

using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

int main(int argc, char** argv)
{
  OEInterface itf(InterfaceData);
  OEConfigureSplitMolComplexOptions(itf);

  if(! OEParseCommandLine(itf, argc, argv))
    OEThrow.Fatal("Unable to interpret command line!");

  oemolistream ims;
  if (itf.Get<unsigned>("-modelnum") != 1u)
    ims.SetFlavor(OEFormat::PDB,
                  OEGetDefaultIFlavor(OEFormat::PDB) & ~OEIFlavor::PDB::ENDM);

  const std::string inputFile = itf.Get<std::string>("-in");
  if (! ims.open(inputFile))
    OEThrow.Fatal("Unable to open %s for reading", inputFile.c_str());

  OEGraphMol inmol;
  OEReadMolecule(ims, inmol);

  oemolostream oms;
  const std::string outFile = itf.Get<std::string>("-out");
  if (! oms.open(outFile))
    OEThrow.Fatal("Unable to open %s for writing", outFile.c_str());

  OESplitMolComplexOptions opts;
  OESetupSplitMolComplexOptions(opts, itf);

  if (itf.Get<bool>("-verbose"))
    OEThrow.SetLevel(OEErrorLevel::Verbose);

  std::vector<OEAtomBondSet> frags;

  if (! OEGetMolComplexFragments(frags, inmol, opts))
    OEThrow.Fatal("Unable to split mol complex from %s", inputFile.c_str());

  const unsigned numSites = OECountMolComplexSites(frags);
  OEThrow.Verbose("sites %d", numSites);

  OEGraphMol lig, prot, wat, other;

  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > lfilter(opts.GetLigandFilter());
  if (! OECombineMolComplexFragments(lig, frags, opts, *lfilter))
    OEThrow.Fatal("Unable to split ligand from %s", inputFile.c_str());

  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > pfilter(opts.GetProteinFilter());
  if (! OECombineMolComplexFragments(prot, frags, opts, *pfilter))
    OEThrow.Fatal("Unable to split protein complex from %s", inputFile.c_str());

  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > wfilter(opts.GetWaterFilter());
  if (! OECombineMolComplexFragments(wat, frags, opts, *wfilter))
    OEThrow.Fatal("Unable to split waters from %s", inputFile.c_str());

  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > ofilter(opts.GetOtherFilter());
  if (! OECombineMolComplexFragments(other, frags, opts, *ofilter))
    OEThrow.Fatal("Unable to split other mols from %s", inputFile.c_str());

  if (lig.NumAtoms() != 0u)
  {
    OEThrow.Verbose("  lig %s", lig.GetTitle());
    OEWriteMolecule(oms, lig);
  }
  if (prot.NumAtoms() != 0u)
  {
    OEThrow.Verbose(" prot %s", prot.GetTitle());
    OEWriteMolecule(oms, prot);
  }
  if (wat.NumAtoms() != 0u)
  {
    OEThrow.Verbose("  wat %s", wat.GetTitle());
    OEWriteMolecule(oms, wat);
  }
  if (other.NumAtoms() != 0u)
  {
    OEThrow.Verbose("other %s", other.GetTitle());
    OEWriteMolecule(oms, other);
  }

  oms.close();

  return 0;
}

Splitting a Macro-molecular Complex Into Fragments

//**********************************************************************
//  Copyright (C) 2015 by OpenEye Scientific Software, Inc.
//***********************************************************************
// split the input molecule into components as individual fragments

#include <openeye.h>

#include <oechem.h>
#include <oebio.h>
#include "splitmolcomplexfrags.itf"

using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

int main(int argc, char** argv)
{
  OEInterface itf(InterfaceData);
  OEConfigureSplitMolComplexOptions(itf);

  if(! OEParseCommandLine(itf, argc, argv))
    OEThrow.Fatal("Unable to interpret command line!");

  oemolistream ims;
  if (itf.Get<unsigned>("-modelnum") != 1u)
    ims.SetFlavor(OEFormat::PDB,
                  OEGetDefaultIFlavor(OEFormat::PDB) & ~OEIFlavor::PDB::ENDM);

  const std::string inputFile = itf.Get<std::string>("-in");
  if (! ims.open(inputFile))
    OEThrow.Fatal("Unable to open %s for reading", inputFile.c_str());

  OEGraphMol inmol;
  OEReadMolecule(ims, inmol);

  oemolostream oms;
  const std::string outFile = itf.Get<std::string>("-out");
  if (! oms.open(outFile))
    OEThrow.Fatal("Unable to open %s for writing", outFile.c_str());

  OESplitMolComplexOptions opts;
  OESetupSplitMolComplexOptions(opts, itf);

  if (itf.Get<bool>("-verbose"))
  { // don't bother counting sites unless we're going to print them
    const unsigned numSites = OECountMolComplexSites(inmol, opts);
    OEThrow.SetLevel(OEErrorLevel::Verbose);
    OEThrow.Verbose("sites %d", numSites);
  }

  for(OEIter<OEMolBase>frag=OEGetMolComplexComponents(inmol,opts); frag;++frag)
  {
    OEThrow.Verbose("frag %s", frag->GetTitle());
    OEWriteMolecule(oms, frag);
  }

  oms.close();

  return 0;
}

Preparing a Protein

//**********************************************************************
//  Copyright (C) 2016 by OpenEye Scientific Software, Inc.
//***********************************************************************
// prepare a molecule: alts, hydrogens, split ligand

#include <openeye.h>

#include <string>

#include <oechem.h>
#include <oebio.h>
#include "proteinprep.itf"

using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

using namespace std;

unsigned WaterProcess(const string & processName)
{
  if (processName == "fullsearch")
    return OEPlaceHydrogensWaterProcessing::FullSearch;
  else if (processName == "focused")
      return OEPlaceHydrogensWaterProcessing::Focused;
  return OEPlaceHydrogensWaterProcessing::Ignore;
}

int main(int argc, char** argv)
{
  OEInterface itf(InterfaceData);
  OEConfigureSplitMolComplexOptions(itf,
                                    OESplitMolComplexSetup::All              &
                                ~ ( OESplitMolComplexSetup::CovBondTreatment |
                                    OESplitMolComplexSetup::CovCofactor )  );

  if(! OEParseCommandLine(itf, argc, argv))
    OEThrow.Fatal("Unable to interpret command line!");

  const bool verbose = itf.Get<bool>("-verbose");
  if (verbose)
    OEThrow.SetLevel(OEErrorLevel::Verbose);

  const string altProcess = itf.Get<string>("-alts");
  const bool keepAlts     = (altProcess != string("a"));
  const bool highestOcc   = (altProcess == string("occupancy"));
  const bool compareAlts  = (altProcess == string("compare"));

  const unsigned siteNum= itf.Get<unsigned>("-bindingsitenum");
  const bool allSites   = (siteNum == 0u);
  const bool otherModel = (itf.Get<unsigned>("-modelnum") != 1u);

  const bool placeHyd = itf.Get<bool>("-placehydrogens");
  const bool splitlig = itf.Has<string>("-ligout");

  const string watProcessName = itf.Get<string>("-waterprocessing");
  const unsigned waterProcess = WaterProcess(watProcessName);

  const bool standardize = itf.Get<bool>("-standardizehyd");
  const double badclash  = itf.Get<double>("-clashcutoff");
  const double flipbias  = itf.Get<double>("-flipbias");
  const double maxStates = itf.Get<double>("-maxsubstates");

  unsigned flavor = OEIFlavor::PDB::Default | OEIFlavor::PDB::DATA;
  if (keepAlts)
    flavor |= OEIFlavor::PDB::ALTLOC;
  if (otherModel)
    flavor &= ~ OEIFlavor::PDB::ENDM;

  oemolistream ims;
  ims.SetFlavor(OEFormat::PDB, flavor);

  const string inputFile = itf.Get<string>("-in");
  if (! ims.open(inputFile))
    OEThrow.Fatal("Unable to open %s for reading.", inputFile.c_str());

  if (! OEIs3DFormat(ims.GetFormat()))
    OEThrow.Fatal("%s is not in a 3D format.", inputFile.c_str());

  const unsigned inftype = OEGetFileType(OEGetFileExtension(inputFile.c_str()));
  if ((inftype == OEFormat::PDB) && (! keepAlts))
    OEThrow.Verbose("Default processing of alt locations (keep just 'A' and ' ').");

  OESplitMolComplexOptions sopt;
  OESetupSplitMolComplexOptions(sopt, itf);

  OEGraphMol inmol;
  if (! OEReadMolecule(ims, inmol))
    OEThrow.Fatal("Unable to read %s.", inputFile.c_str());

  ims.close();

  if (! inmol)
    OEThrow.Fatal("Input molecule %s contains no atoms.", inputFile.c_str());

  if (string(inmol.GetTitle()) == string(""))
    inmol.SetTitle("input mol");

  OEThrow.Verbose("Processing %s.", inmol.GetTitle());

  if (! OEHasResidues(inmol))
    OEPerceiveResidues(inmol, OEPreserveResInfo::All);

  if (highestOcc || compareAlts)
  {
    OEAltLocationFactory alf(inmol);
    if (alf.GetGroupCount() != 0u)
    {
      if (highestOcc)
      {
        OEThrow.Verbose("Dropping alternate locations from input.");
        alf.MakePrimaryAltMol(inmol);
      }
      else if (compareAlts)
      {
        OEThrow.Verbose("Fixing alternate location issues.");
        inmol = alf.GetSourceMol();
      }
    }
  }

  OEGraphMol outmol;
  if (allSites)
    outmol = inmol;
  else
  {
    OEThrow.Verbose("Splitting out selected complex.");

    OESplitMolComplexOptions soptSiteSel(sopt);
    soptSiteSel.SetSplitCovalent(false); // do any cov lig splitting later

    vector<OEAtomBondSet> frags;
    if (! OEGetMolComplexFragments(frags, inmol, soptSiteSel))
      OEThrow.Fatal("Unable to fragment %s.", inmol.GetTitle());

    const unsigned howManySites = OECountMolComplexSites(frags);
    if (howManySites < siteNum)
    {
      OEThrow.Warning("Binding site count (%d) less than requested site (%d) in %s.",
                      howManySites, siteNum, inmol.GetTitle());
      return 0;
    }

    if (! OECombineMolComplexFragments(outmol, frags, soptSiteSel))
      OEThrow.Fatal("Unable to collect fragments from %s.", inmol.GetTitle());

    if (! outmol)
      OEThrow.Fatal("No fragments selected from %s.", inmol.GetTitle());
  }

  if (placeHyd)
  {
    OEThrow.Verbose("Adding hydrogens to complex.");

    OEPlaceHydrogensOptions hopt;
    hopt.SetAltsMustBeCompatible(compareAlts);
    hopt.SetStandardizeBondLen(standardize);
    hopt.SetWaterProcessing(waterProcess);
    hopt.SetBadClashOverlapDistance(badclash);
    hopt.SetFlipBiasScale(flipbias);
    hopt.SetMaxSubstateCutoff(maxStates);

    if (verbose)
    {
      OEPlaceHydrogensDetails details;
      if (! OEPlaceHydrogens(outmol, details, hopt))
        OEThrow.Fatal("Unable to place hydrogens and get details on %s.", inmol.GetTitle());
      OEThrow.Verbose(details.Describe());
    }
    else
    {
      if (! OEPlaceHydrogens(outmol, hopt))
        OEThrow.Fatal("Unable to place hydrogens on %s.", inmol.GetTitle());
    }
  }

  oemolostream oms1;
  const string cplxFile = itf.Get<string>("-cplxout");
  if (! oms1.open(cplxFile))
    OEThrow.Fatal("Unable to open %s for writing.", cplxFile.c_str());

  if (splitlig)
  {
    OEThrow.Verbose("Splitting ligand from complex.");

    vector<OEAtomBondSet> frags;
    if (! OEGetMolComplexFragments(frags, outmol, sopt))
      OEThrow.Fatal("Unable to fragment complex from %s.", inmol.GetTitle());

    OEOwnedPtr< OEUnaryPredicate<OERoleSet> > lfilter(sopt.GetLigandFilter());

    OEGraphMol protComplex;
    if (! OECombineMolComplexFragments(protComplex,
                                       frags,
                                       sopt,
                                       OENot<OERoleSet>(*lfilter)))
      OEThrow.Fatal("Unable to collect complex from %s.", inmol.GetTitle());

    if (! protComplex)
      OEThrow.Warning("No complex identified in %s.", inmol.GetTitle());
    else
      OEWriteMolecule(oms1, protComplex);

    OEGraphMol lig;
    if (! OECombineMolComplexFragments(lig, frags, sopt, *lfilter))
      OEThrow.Fatal("Unable to collect ligand from %s.", inmol.GetTitle());

    if (! lig)
      OEThrow.Warning("No ligand identified in %s.", inmol.GetTitle());
    else
    {
      oemolostream oms2;
      if (splitlig)
      {
        const string ligFile = itf.Get<string>("-ligout");
        if (! oms2.open(ligFile))
          OEThrow.Fatal("Unable to open %s for writing.", ligFile.c_str());
      }

      OEThrow.Verbose("Ligand: %s", lig.GetTitle());
      OEWriteMolecule(oms2, lig);
      oms2.close();
    }
  }
  else
    OEWriteMolecule(oms1, outmol);

  oms1.close();

  return 0;
}

Perceive and Print Protein-Ligand Interactions

/****************************************************************************
* Copyright (C) 2015-2016 OpenEye Scientific Software, Inc.
*****************************************************************************
* Print protein-ligand interactions
****************************************************************************/

#include <openeye.h>

#include <set>

#include <oesystem.h>
#include <oechem.h>
#include <oebio.h>

#include "printinteractions.itf"

using namespace std;
using namespace OESystem;
using namespace OEChem;
using namespace OEBio;

static string GetResidueName(const OEResidue& residue);

static void PrintInteraction(const OEInteractionHint& inter);
static void PrintResidueInteractions(const OEInteractionHintContainer& asite, const OEResidue& residue);
static void PrintLigandAtomInteractions(const OEInteractionHintContainer& asite, const OEAtomBase* atom);

int main(int argc, char** argv)
{
  OEInterface itf(InterfaceData);
  OEConfigureSplitMolComplexOptions(itf, OESplitMolComplexSetup::LigName);

  if(! OEParseCommandLine(itf, argc, argv))
    OEThrow.Fatal("Unable to interpret command line!");

  const string iname = itf.Get<string>("-complex");

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

  if (!OEReadMolecule(ifs, complexmol))
    OEThrow.Fatal("Unable to read molecule from %s" , iname.c_str());

  if (!OEHasResidues(complexmol))
    OEPerceiveResidues(complexmol, OEPreserveResInfo::All);

  // Separate ligand and protein

  OESplitMolComplexOptions sopts;
  OESetupSplitMolComplexOptions(sopts, itf);

  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > pfilter(sopts.GetProteinFilter());
  OEOwnedPtr< OEUnaryPredicate<OERoleSet> > wfilter(sopts.GetWaterFilter());
  sopts.SetProteinFilter(OEOr<OERoleSet>(*pfilter, *wfilter));
  sopts.SetWaterFilter(OEMolComplexFilterFactory(OEMolComplexFilterCategory::Nothing));

  OEGraphMol lig, prot, water, other;
  OESplitMolComplex(lig, prot, water, other, complexmol, sopts);

  if (lig.NumAtoms() == 0)
    OEThrow.Fatal("Cannot separate complex!");

   OEInteractionHintContainer asite(prot, lig);

  if (!OEIsValidActiveSite(asite))
    OEThrow.Fatal("Cannot initialize active site!");

  OEPerceiveInteractionHints(asite);

  cout << "Number of interactions: " << asite.NumInteractions();
  for (OEIter<const OEInteractionHintTypeBase> ti = OEGetActiveSiteInteractionHintTypes(); ti; ++ti)
  {
    const OEInteractionHintTypeBase* itype = ti;
    OEHasInteractionHintType ipred(*itype);
    const unsigned int nrinters = asite.NumInteractions(ipred);
    if (nrinters == 0)
      continue;
    cout << itype->GetName() <<  " :" << endl;
    for (OEIter<const OEInteractionHint> ii = asite.GetInteractions(ipred); ii; ++ii)
      PrintInteraction(*ii);
  }

  cout << "\nResidue interactions: " << endl;
  const OEMolBase* protein = asite.GetMolecule(OEProteinInteractionHintComponent());
  for (OEIter<OEResidue> ri = OEGetResidues(*protein); ri; ++ri)
    PrintResidueInteractions(asite, *ri);

  cout << "\nLigand atom interactions: " << endl;  
  const OEMolBase* ligand = asite.GetMolecule(OELigandInteractionHintComponent());
  for (OEIter<OEAtomBase> ai = ligand->GetAtoms(); ai; ++ai)
    PrintLigandAtomInteractions(asite, ai);

  return 0;
}

static string GetResidueName(const OEResidue& residue)
{
  string name = residue.GetName() + string(" ");
  name += OENumberToString(residue.GetResidueNumber()) + string(" ");
  name += residue.GetChainID();
  return name;
}

static void PrintFragment(const OEInteractionHintFragment& frag)
{
  const OEInteractionHintComponentTypeBase& fragtype = frag.GetComponentType();
  if (fragtype == OELigandInteractionHintComponent())
    cout << "ligand: ";
  else if (fragtype == OEProteinInteractionHintComponent())
    cout << "protein: ";
  for (OEIter<const OEAtomBase> ai = frag.GetAtoms(); ai; ++ai)
    cout << ai->GetIdx() << " " << OEGetAtomicSymbol(ai->GetAtomicNum()) << " ";
}

static void PrintInteraction(const OEInteractionHint& inter)
{
  const OEInteractionHintFragment* bgnfrag = inter.GetBgnFragment();
  if (bgnfrag)
    PrintFragment(*bgnfrag);
  const OEInteractionHintFragment* endfrag = inter.GetEndFragment();
  if (endfrag)
    PrintFragment(*endfrag);
  cout << endl;
}

static void PrintResidueInteractions(const OEInteractionHintContainer& asite, const OEResidue& residue)
{
  set<const OEAtomBase*> ligatoms;
  OEHasResidueInteractionHint ipred(residue);
  for (OEIter<const OEInteractionHint> ii = asite.GetInteractions(ipred); ii; ++ii)
  {
    const OEInteractionHintFragment* ligfrag = ii->GetFragment(OELigandInteractionHintComponent());
    if (ligfrag)
    {
      for (OEIter<const OEAtomBase> ai = ligfrag->GetAtoms(); ai; ++ai)
        ligatoms.insert(ai);
    }
  }
  
  if (ligatoms.size() != 0)
  {
    cout << GetResidueName(residue) << " : ";
    for (set<const OEAtomBase*>::const_iterator ai = ligatoms.begin(); ai != ligatoms.end(); ++ai)
      cout << (*ai)->GetIdx() << " " << OEGetAtomicSymbol((*ai)->GetAtomicNum()) << " ";
    cout << endl;
  }
}

static void PrintLigandAtomInteractions(const OEInteractionHintContainer& asite, const OEAtomBase* atom)
{
  set<string> resnames;
  OEHasInteractionHint ipred(atom);
  for (OEIter<const OEInteractionHint> ii = asite.GetInteractions(ipred); ii; ++ii)
  {
    const OEInteractionHintFragment* profrag = ii->GetFragment(OEProteinInteractionHintComponent());
    if (profrag)
    {
      for (OEIter<const OEAtomBase> ai = profrag->GetAtoms(); ai; ++ai)
      {
        const OEResidue& residue = OEAtomGetResidue(ai);
        resnames.insert(GetResidueName(residue));
      }
    }
  }
  if (resnames.size() != 0)
  {
    cout << atom->GetIdx() << " " << OEGetAtomicSymbol(atom->GetAtomicNum()) << " : ";
    for (set<string>::const_iterator ri = resnames.begin(); ri != resnames.end(); ++ri)
      cout << *ri << " ";
    cout << endl;
  }
}