QueryOps.h

Go to the documentation of this file.
00001 //
00002 //  Copyright (C) 2003-2010 Greg Landrum and Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved @@
00005 //  This file is part of the RDKit.
00006 //  The contents are covered by the terms of the BSD license
00007 //  which is included in the file license.txt, found at the root
00008 //  of the RDKit source tree.
00009 //
00010 
00011 //! \file QueryOps.h
00012 /*!
00013     \brief Includes a bunch of functionality for handling Atom and Bond queries.
00014 */
00015 #ifndef _RD_QUERY_OPS_H
00016 #define _RD_QUERY_OPS_H
00017 
00018 #include <GraphMol/RDKitBase.h>
00019 #include <Query/QueryObjects.h>
00020 
00021 namespace RDKit{
00022   typedef Queries::Query<bool,Atom const *,true> ATOM_BOOL_QUERY;
00023   typedef Queries::Query<bool,Bond const *,true> BOND_BOOL_QUERY;
00024 
00025   typedef Queries::AndQuery<int,Atom const *,true> ATOM_AND_QUERY;
00026   typedef Queries::AndQuery<int,Bond const *,true> BOND_AND_QUERY;
00027 
00028   typedef Queries::OrQuery<int,Atom const *,true> ATOM_OR_QUERY;
00029   typedef Queries::OrQuery<int,Bond const *,true> BOND_OR_QUERY;
00030 
00031   typedef Queries::XOrQuery<int,Atom const *,true> ATOM_XOR_QUERY;
00032   typedef Queries::XOrQuery<int,Bond const *,true> BOND_XOR_QUERY;
00033 
00034   typedef Queries::EqualityQuery<int,Atom const *,true> ATOM_EQUALS_QUERY;
00035   typedef Queries::EqualityQuery<int,Bond const *,true> BOND_EQUALS_QUERY;
00036 
00037   typedef Queries::GreaterQuery<int,Atom const *,true> ATOM_GREATER_QUERY;
00038   typedef Queries::GreaterQuery<int,Bond const *,true> BOND_GREATER_QUERY;
00039 
00040   typedef Queries::GreaterEqualQuery<int,Atom const *,true> ATOM_GREATEREQUAL_QUERY;
00041   typedef Queries::GreaterEqualQuery<int,Bond const *,true> BOND_GREATEREQUAL_QUERY;
00042 
00043   typedef Queries::LessQuery<int,Atom const *,true> ATOM_LESS_QUERY;
00044   typedef Queries::LessQuery<int,Bond const *,true> BOND_LESS_QUERY;
00045 
00046   typedef Queries::LessEqualQuery<int,Atom const *,true> ATOM_LESSEQUAL_QUERY;
00047   typedef Queries::LessEqualQuery<int,Bond const *,true> BOND_LESSEQUAL_QUERY;
00048 
00049   typedef Queries::RangeQuery<int,Atom const *,true> ATOM_RANGE_QUERY;
00050   typedef Queries::RangeQuery<int,Bond const *,true> BOND_RANGE_QUERY;
00051 
00052   typedef Queries::SetQuery<int,Atom const *,true> ATOM_SET_QUERY;
00053   typedef Queries::SetQuery<int,Bond const *,true> BOND_SET_QUERY;
00054 
00055   typedef Queries::Query<int,Bond const *,true> BOND_NULL_QUERY;
00056   typedef Queries::Query<int,Atom const *,true> ATOM_NULL_QUERY;
00057 
00058   // -------------------------------------------------
00059   // common atom queries
00060 
00061   static int queryAtomAromatic(Atom const * at) { return at->getIsAromatic(); };
00062   static int queryAtomAliphatic(Atom const * at) { return !(at->getIsAromatic()); };
00063   static int queryAtomExplicitDegree(Atom const * at) { return at->getDegree(); };
00064   static int queryAtomTotalDegree(Atom const * at) { return at->getTotalDegree(); };
00065   static int queryAtomHeavyAtomDegree(Atom const * at) { return at->getTotalDegree()-at->getTotalNumHs(true); };
00066   static int queryAtomHCount(Atom const * at) { return at->getTotalNumHs(true); };
00067   static int queryAtomImplicitValence(Atom const * at) { return at->getImplicitValence(); };
00068   static int queryAtomExplicitValence(Atom const * at) { return at->getExplicitValence() - at->getNumExplicitHs(); };
00069   static int queryAtomTotalValence(Atom const * at) { return at->getExplicitValence()+at->getImplicitValence(); };
00070   static int queryAtomUnsaturated(Atom const * at) { return static_cast<int>(at->getDegree())<at->getExplicitValence(); };
00071   static int queryAtomNum(Atom const * at) { return at->getAtomicNum(); };
00072   static int massIntegerConversionFactor=1000;
00073   static int queryAtomMass(Atom const * at) {
00074     return static_cast<int>(round(massIntegerConversionFactor*at->getMass()));
00075   };
00076   static int queryAtomFormalCharge(Atom const * at) { 
00077       return static_cast<int>(at->getFormalCharge()); 
00078   };
00079   static int queryAtomHybridization(Atom const * at) { return at->getHybridization(); };
00080   unsigned int queryAtomBondProduct(Atom const * at);
00081   unsigned int queryAtomAllBondProduct(Atom const * at);
00082     
00083     
00084   // -------------------------------------------------
00085   // common bond queries
00086 
00087   static int queryBondOrder(Bond const * bond) { return static_cast<int>(bond->getBondType()); };
00088   static int queryBondDir(Bond const * bond) { return static_cast<int>(bond->getBondDir()); };
00089   static int queryIsBondInNRings(Bond const * at) {
00090     return at->getOwningMol().getRingInfo()->numBondRings(at->getIdx());
00091   };
00092 
00093   // -------------------------------------------------
00094   // ring queries 
00095 
00096   static int queryIsAtomInNRings(Atom const * at) {
00097     return at->getOwningMol().getRingInfo()->numAtomRings(at->getIdx());
00098   };
00099   static int queryIsAtomInRing(Atom const * at) {
00100     return at->getOwningMol().getRingInfo()->numAtomRings(at->getIdx())!=0;
00101   };
00102   static int queryIsBondInRing(Bond const * bond) {
00103     return bond->getOwningMol().getRingInfo()->numBondRings(bond->getIdx())!=0;
00104   };
00105   static int queryAtomMinRingSize(Atom const *at){
00106     return at->getOwningMol().getRingInfo()->minAtomRingSize(at->getIdx());
00107   };
00108   static int queryBondMinRingSize(Bond const *bond){
00109     return bond->getOwningMol().getRingInfo()->minBondRingSize(bond->getIdx());
00110   };
00111 
00112   static int queryAtomRingBondCount(Atom const *at) {
00113     // EFF: cache this result
00114     int res=0;
00115     ROMol::OBOND_ITER_PAIR atomBonds=at->getOwningMol().getAtomBonds(at);
00116     while(atomBonds.first != atomBonds.second){
00117       unsigned int bondIdx=at->getOwningMol().getTopology()[*atomBonds.first]->getIdx();
00118       if(at->getOwningMol().getRingInfo()->numBondRings(bondIdx)) {
00119         res++;
00120       }
00121       ++atomBonds.first;  
00122     }
00123     return res;
00124   }
00125 
00126   template <int tgt>
00127   int queryAtomIsInRingOfSize(Atom const *at) {
00128     if(at->getOwningMol().getRingInfo()->isAtomInRingOfSize(at->getIdx(),tgt)){
00129       return tgt;
00130     } else {
00131       return 0;
00132     }
00133   };
00134   template <int tgt>
00135   int queryBondIsInRingOfSize(Bond const *bond) {
00136     if(bond->getOwningMol().getRingInfo()->isBondInRingOfSize(bond->getIdx(),tgt)){
00137       return tgt;
00138     } else {
00139       return 0;
00140     }
00141   };
00142 
00143   
00144   //! returns a Query for matching atomic number
00145   ATOM_EQUALS_QUERY *makeAtomNumEqualsQuery(int what);
00146   //! returns a Query for matching implicit valence
00147   ATOM_EQUALS_QUERY *makeAtomImplicitValenceQuery(int what);
00148   //! returns a Query for matching explicit valence
00149   ATOM_EQUALS_QUERY *makeAtomExplicitValenceQuery(int what);
00150   //! returns a Query for matching total valence
00151   ATOM_EQUALS_QUERY *makeAtomTotalValenceQuery(int what);
00152   //! returns a Query for matching explicit valence
00153   ATOM_EQUALS_QUERY *makeAtomExplicitDegreeQuery(int what);
00154   //! returns a Query for matching atomic degree
00155   ATOM_EQUALS_QUERY *makeAtomTotalDegreeQuery(int what);
00156   //! returns a Query for matching hydrogen count
00157   ATOM_EQUALS_QUERY *makeAtomHCountQuery(int what);
00158   //! returns a Query for matching the \c isAromatic flag
00159   ATOM_EQUALS_QUERY *makeAtomAromaticQuery();
00160   //! returns a Query for matching aliphatic atoms
00161   ATOM_EQUALS_QUERY *makeAtomAliphaticQuery();
00162   //! returns a Query for matching atoms with a particular mass (for isotopes)
00163   ATOM_EQUALS_QUERY *makeAtomMassQuery(int what);
00164   //! returns a Query for matching formal charge
00165   ATOM_EQUALS_QUERY *makeAtomFormalChargeQuery(int what);
00166   //! returns a Query for matching hybridization
00167   ATOM_EQUALS_QUERY *makeAtomHybridizationQuery(int what);
00168   //! returns a Query for matching atoms with unsaturation:
00169   ATOM_EQUALS_QUERY *makeAtomUnsaturatedQuery();
00170 
00171   //! returns a Query for matching ring atoms
00172   ATOM_EQUALS_QUERY *makeAtomInRingQuery();
00173   //! returns a Query for matching atoms in a particular number of rings
00174   ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what);
00175   //! returns a Query for matching atoms in rings of a particular size
00176   ATOM_EQUALS_QUERY *makeAtomInRingOfSizeQuery(int tgt);
00177   //! returns a Query for matching an atom's minimum ring size
00178   ATOM_EQUALS_QUERY *makeAtomMinRingSizeQuery(int tgt);
00179   //! returns a Query for matching atoms with a particular number of ring bonds
00180   ATOM_EQUALS_QUERY *makeAtomRingBondCountQuery(int what);
00181 
00182   //! returns a Query for matching bond orders
00183   BOND_EQUALS_QUERY *makeBondOrderEqualsQuery(Bond::BondType what);
00184   //! returns a Query for matching bond directions
00185   BOND_EQUALS_QUERY *makeBondDirEqualsQuery(Bond::BondDir what);
00186   //! returns a Query for matching ring bonds
00187   BOND_EQUALS_QUERY *makeBondIsInRingQuery();
00188   //! returns a Query for matching bonds in rings of a particular size
00189   BOND_EQUALS_QUERY *makeBondInRingOfSizeQuery(int what);
00190   //! returns a Query for matching a bond's minimum ring size
00191   BOND_EQUALS_QUERY *makeBondMinRingSizeQuery(int what);
00192   //! returns a Query for matching bonds in a particular number of rings
00193   BOND_EQUALS_QUERY *makeBondInNRingsQuery(int tgt);
00194 
00195   //! returns a Query for matching any bond
00196   BOND_NULL_QUERY *makeBondNullQuery();
00197   //! returns a Query for matching any atom
00198   ATOM_NULL_QUERY *makeAtomNullQuery();
00199 
00200   static int queryAtomRingMembership(Atom const *at) {
00201     return static_cast<int>(at->getOwningMol().getRingInfo()->numAtomRings(at->getIdx()));
00202   }
00203   // I'm pretty sure that this typedef shouldn't be necessary,
00204   // but VC++ generates a warning about const Atom const * in
00205   // the definition of Match, then complains about an override
00206   // that differs only by const/volatile (c4301), then generates
00207   // incorrect code if we don't do this... so let's do it.
00208   typedef Atom const *ConstAtomPtr;
00209   
00210   class AtomRingQuery : public Queries::EqualityQuery<int, ConstAtomPtr,true> {
00211   public:
00212     AtomRingQuery() : Queries::EqualityQuery<int,ConstAtomPtr,true>(-1) {
00213       // default is to just do a number of rings query:
00214       this->setDescription("AtomInNRings");
00215       this->setDataFunc(queryAtomRingMembership);
00216     };
00217     explicit AtomRingQuery(int v) : Queries::EqualityQuery<int,ConstAtomPtr,true>(v) {
00218       // default is to just do a number of rings query:
00219       this->setDescription("AtomInNRings");
00220       this->setDataFunc(queryAtomRingMembership);
00221     };
00222 
00223     virtual bool Match(const ConstAtomPtr what) const {
00224       int v = this->TypeConvert(what,Queries::Int2Type<true>());
00225       bool res;
00226       if(this->d_val<0){
00227         res = v!=0;
00228       } else {
00229         res=!Queries::queryCmp(v,this->d_val,this->d_tol);
00230       }
00231       if(this->getNegation()){
00232         res=!res;
00233       }
00234       return res;
00235     }
00236 
00237     //! returns a copy of this query
00238     Queries::Query<int,ConstAtomPtr,true> *
00239     copy() const {
00240       AtomRingQuery *res = new AtomRingQuery(this->d_val);
00241       res->setNegation(getNegation());
00242       res->setTol(this->getTol());
00243       res->d_description = this->d_description;
00244       res->d_dataFunc = this->d_dataFunc;
00245       return res;
00246     }
00247   };
00248   
00249   //! allows use of recursive structure queries (e.g. recursive SMARTS)
00250   class RecursiveStructureQuery : public Queries::SetQuery<int,Atom const *,true> {
00251   public:
00252     RecursiveStructureQuery() :
00253       Queries::SetQuery<int,Atom const *,true>(),
00254       d_serialNumber(0)
00255     {
00256       setDataFunc(getAtIdx);
00257       setDescription("RecursiveStructure");
00258     };
00259     //! initialize from an ROMol pointer
00260     /*!
00261       <b>Notes</b>
00262         - this takes over ownership of the pointer
00263     */
00264     RecursiveStructureQuery(ROMol const *query,unsigned int serialNumber=0) :
00265       Queries::SetQuery<int,Atom const *,true>(),
00266       d_serialNumber(serialNumber)
00267     {
00268       setQueryMol(query);
00269       setDataFunc(getAtIdx);
00270       setDescription("RecursiveStructure");
00271     };
00272     //! returns the index of an atom
00273     static int getAtIdx(Atom const *at) { return at->getIdx(); };
00274 
00275     //! sets the molecule we'll use recursively
00276     /*!
00277       <b>Notes</b>
00278         - this takes over ownership of the pointer
00279     */
00280     void setQueryMol(ROMol const *query) {
00281       dp_queryMol.reset(query);
00282     }
00283     //! returns a pointer to our query molecule
00284     ROMol const * getQueryMol() const { return dp_queryMol.get(); };
00285 
00286     //! returns a copy of this query
00287     Queries::Query<int,Atom const *,true> *
00288     copy() const {
00289       RecursiveStructureQuery *res =
00290         new RecursiveStructureQuery();
00291       res->dp_queryMol = dp_queryMol;
00292 
00293       std::set<int>::const_iterator i;
00294       for(i=d_set.begin();i!=d_set.end();i++){
00295         res->insert(*i);
00296       }
00297       res->setNegation(getNegation());
00298       res->d_description = d_description;
00299       res->d_serialNumber=d_serialNumber;
00300       return res;
00301     }
00302     unsigned int getSerialNumber() const { return d_serialNumber; };
00303   
00304   private:
00305     boost::shared_ptr<const ROMol>dp_queryMol;
00306     unsigned int d_serialNumber;
00307   };
00308 
00309   template <typename T>
00310   int nullDataFun(T arg) { return 1; }
00311   template <typename T>
00312   bool nullQueryFun(T arg) { return true; } 
00313   
00314 };
00315 
00316 
00317 #endif