// $Id$ // // Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license // which is included in the file license.txt, found at the root // of the RDKit source tree. // #include "QueryOps.h" #include #include namespace RDKit { // common general queries //! returns a Query for matching atoms with a particular number of ring bonds ATOM_EQUALS_QUERY *makeAtomRingBondCountQuery(int what) { ATOM_EQUALS_QUERY *res = new AtomRingQuery(what); res->setDescription("AtomRingBondCount"); res->setDataFunc(queryAtomRingBondCount); return res; }; ATOM_EQUALS_QUERY *makeAtomInRingOfSizeQuery(int tgt) { RANGE_CHECK(3, tgt, 20); ATOM_EQUALS_QUERY *res = new ATOM_EQUALS_QUERY; res->setVal(tgt); switch (tgt) { case 3: res->setDataFunc(queryAtomIsInRingOfSize<3>); break; case 4: res->setDataFunc(queryAtomIsInRingOfSize<4>); break; case 5: res->setDataFunc(queryAtomIsInRingOfSize<5>); break; case 6: res->setDataFunc(queryAtomIsInRingOfSize<6>); break; case 7: res->setDataFunc(queryAtomIsInRingOfSize<7>); break; case 8: res->setDataFunc(queryAtomIsInRingOfSize<8>); break; case 9: res->setDataFunc(queryAtomIsInRingOfSize<9>); break; case 10: res->setDataFunc(queryAtomIsInRingOfSize<10>); break; case 11: res->setDataFunc(queryAtomIsInRingOfSize<11>); break; case 12: res->setDataFunc(queryAtomIsInRingOfSize<12>); break; case 13: res->setDataFunc(queryAtomIsInRingOfSize<13>); break; case 14: res->setDataFunc(queryAtomIsInRingOfSize<14>); break; case 15: res->setDataFunc(queryAtomIsInRingOfSize<15>); break; case 16: res->setDataFunc(queryAtomIsInRingOfSize<16>); break; case 17: res->setDataFunc(queryAtomIsInRingOfSize<17>); break; case 18: res->setDataFunc(queryAtomIsInRingOfSize<18>); break; case 19: res->setDataFunc(queryAtomIsInRingOfSize<19>); break; case 20: res->setDataFunc(queryAtomIsInRingOfSize<20>); break; } res->setDescription("AtomRingSize"); return res; } BOND_EQUALS_QUERY *makeBondInRingOfSizeQuery(int tgt) { RANGE_CHECK(3, tgt, 20); BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(tgt); switch (tgt) { case 3: res->setDataFunc(queryBondIsInRingOfSize<3>); break; case 4: res->setDataFunc(queryBondIsInRingOfSize<4>); break; case 5: res->setDataFunc(queryBondIsInRingOfSize<5>); break; case 6: res->setDataFunc(queryBondIsInRingOfSize<6>); break; case 7: res->setDataFunc(queryBondIsInRingOfSize<7>); break; case 8: res->setDataFunc(queryBondIsInRingOfSize<8>); break; case 9: res->setDataFunc(queryBondIsInRingOfSize<9>); break; case 10: res->setDataFunc(queryBondIsInRingOfSize<10>); break; case 11: res->setDataFunc(queryBondIsInRingOfSize<11>); break; case 12: res->setDataFunc(queryBondIsInRingOfSize<12>); break; case 13: res->setDataFunc(queryBondIsInRingOfSize<13>); break; case 14: res->setDataFunc(queryBondIsInRingOfSize<14>); break; case 15: res->setDataFunc(queryBondIsInRingOfSize<15>); break; case 16: res->setDataFunc(queryBondIsInRingOfSize<16>); break; case 17: res->setDataFunc(queryBondIsInRingOfSize<17>); break; case 18: res->setDataFunc(queryBondIsInRingOfSize<18>); break; case 19: res->setDataFunc(queryBondIsInRingOfSize<19>); break; case 20: res->setDataFunc(queryBondIsInRingOfSize<20>); break; } res->setDescription("BondRingSize"); return res; } ATOM_EQUALS_QUERY *makeAtomMinRingSizeQuery(int tgt) { RANGE_CHECK(3, tgt, 20); ATOM_EQUALS_QUERY *res = new ATOM_EQUALS_QUERY; res->setVal(tgt); res->setDataFunc(queryAtomMinRingSize); res->setDescription("AtomMinRingSize"); return res; } BOND_EQUALS_QUERY *makeBondMinRingSizeQuery(int tgt) { RANGE_CHECK(3, tgt, 20); BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(tgt); res->setDataFunc(queryBondMinRingSize); res->setDescription("BondMinRingSize"); return res; } unsigned int queryAtomBondProduct(Atom const *at) { ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = at->getOwningMol().getAtomBonds(at); unsigned int prod = 1; while (beg != end) { prod *= static_cast( firstThousandPrimes[at->getOwningMol()[*beg]->getBondType()]); ++beg; } return prod; } unsigned int queryAtomAllBondProduct(Atom const *at) { ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = at->getOwningMol().getAtomBonds(at); unsigned int prod = 1; while (beg != end) { prod *= static_cast( firstThousandPrimes[at->getOwningMol()[*beg]->getBondType()]); ++beg; } for (unsigned int i = 0; i < at->getTotalNumHs(); i++) { prod *= static_cast(firstThousandPrimes[Bond::SINGLE]); } return prod; } ATOM_EQUALS_QUERY *makeAtomImplicitValenceQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomImplicitValence); res->setDescription("AtomImplicitValence"); return res; } ATOM_EQUALS_QUERY *makeAtomExplicitValenceQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomExplicitValence); res->setDescription("AtomExplicitValence"); return res; } ATOM_EQUALS_QUERY *makeAtomTotalValenceQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomTotalValence); res->setDescription("AtomTotalValence"); return res; } ATOM_EQUALS_QUERY *makeAtomNumQuery(int what) { return makeAtomSimpleQuery(what, queryAtomNum, "AtomAtomicNum"); } ATOM_EQUALS_QUERY *makeAtomExplicitDegreeQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomExplicitDegree); res->setDescription("AtomExplicitDegree"); return res; } ATOM_EQUALS_QUERY *makeAtomTotalDegreeQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomTotalDegree); res->setDescription("AtomTotalDegree"); return res; } ATOM_EQUALS_QUERY *makeAtomHCountQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomHCount); res->setDescription("AtomHCount"); return res; } ATOM_EQUALS_QUERY *makeAtomImplicitHCountQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomImplicitHCount); res->setDescription("AtomImplicitHCount"); return res; } ATOM_EQUALS_QUERY *makeAtomHasImplicitHQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomHasImplicitH); res->setDescription("AtomHasImplicitH"); return res; } ATOM_EQUALS_QUERY *makeAtomAromaticQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomAromatic); res->setDescription("AtomIsAromatic"); return res; } ATOM_EQUALS_QUERY *makeAtomAliphaticQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomAliphatic); res->setDescription("AtomIsAliphatic"); return res; } ATOM_EQUALS_QUERY *makeAtomUnsaturatedQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomUnsaturated); res->setDescription("AtomUnsaturated"); return res; } ATOM_EQUALS_QUERY *makeAtomMassQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery( massIntegerConversionFactor * what, queryAtomMass); res->setDescription("AtomMass"); return res; } ATOM_EQUALS_QUERY *makeAtomIsotopeQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomIsotope); res->setDescription("AtomIsotope"); return res; } ATOM_EQUALS_QUERY *makeAtomFormalChargeQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomFormalCharge); res->setDescription("AtomFormalCharge"); return res; } ATOM_EQUALS_QUERY *makeAtomHybridizationQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomHybridization); res->setDescription("AtomHybridization"); return res; } ATOM_EQUALS_QUERY *makeAtomNumRadicalElectronsQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery( what, queryAtomNumRadicalElectrons); res->setDescription("AtomNumRadicalElectrons"); return res; } ATOM_EQUALS_QUERY *makeAtomHasChiralTagQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomHasChiralTag); res->setDescription("AtomHasChiralTag"); return res; } ATOM_EQUALS_QUERY *makeAtomMissingChiralTagQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomMissingChiralTag); res->setDescription("AtomMissingChiralTag"); return res; } ATOM_EQUALS_QUERY *makeAtomInRingQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryIsAtomInRing); res->setDescription("AtomInRing"); return res; } ATOM_EQUALS_QUERY *makeAtomHasRingBondQuery() { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(true, queryAtomHasRingBond); res->setDescription("AtomHasRingBond"); return res; } ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what) { ATOM_EQUALS_QUERY *res; res = makeAtomSimpleQuery(what, queryIsAtomInNRings); res->setDescription("AtomInNRings"); return res; } BOND_EQUALS_QUERY *makeBondOrderEqualsQuery(Bond::BondType what) { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(what); res->setDataFunc(queryBondOrder); res->setDescription("BondOrder"); return res; } BOND_EQUALS_QUERY *makeBondDirEqualsQuery(Bond::BondDir what) { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(what); res->setDataFunc(queryBondDir); res->setDescription("BondDir"); return res; } BOND_EQUALS_QUERY *makeBondHasStereoQuery() { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(true); res->setDataFunc(queryBondHasStereo); res->setDescription("BondStereo"); return res; } BOND_EQUALS_QUERY *makeBondIsInRingQuery() { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(true); res->setDataFunc(queryIsBondInRing); res->setDescription("BondInRing"); return res; } BOND_EQUALS_QUERY *makeBondInNRingsQuery(int what) { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(what); res->setDataFunc(queryIsBondInNRings); res->setDescription("BondInNRings"); return res; } BOND_NULL_QUERY *makeBondNullQuery() { BOND_NULL_QUERY *res = new BOND_NULL_QUERY; res->setDataFunc(nullDataFun); res->setMatchFunc(nullQueryFun); res->setDescription("BondNull"); return res; } ATOM_NULL_QUERY *makeAtomNullQuery() { ATOM_NULL_QUERY *res = new ATOM_NULL_QUERY; res->setDataFunc(nullDataFun); res->setMatchFunc(nullQueryFun); res->setDescription("AtomNull"); return res; } bool isComplexQuery(const Bond *b) { if (!b->hasQuery()) return false; // negated things are always complex: if (b->getQuery()->getNegation()) return true; std::string descr = b->getQuery()->getDescription(); if (descr == "BondOrder") return false; if (descr == "BondAnd" || descr == "BondXor") return true; if (descr == "BondOr") { // detect the types of queries that appear for unspecified bonds in SMARTS: if (b->getQuery()->endChildren() - b->getQuery()->beginChildren() == 2) { for (Bond::QUERYBOND_QUERY::CHILD_VECT_CI child = b->getQuery()->beginChildren(); child != b->getQuery()->endChildren(); ++child) { if ((*child)->getDescription() != "BondOrder" || (*child)->getNegation()) return true; if (static_cast(child->get())->getVal() != Bond::SINGLE && static_cast(child->get())->getVal() != Bond::AROMATIC) return true; return false; } } } return true; } bool _complexQueryHelper(Atom::QUERYATOM_QUERY const *query, bool &hasAtNum) { if (!query) return false; if (query->getNegation()) return true; std::string descr = query->getDescription(); // std::cerr<<" |"<::CHILD_VECT_CI childIt = query->beginChildren(); while (childIt != query->endChildren()) { if (_complexQueryHelper(childIt->get(), hasAtNum)) return true; ++childIt; } } return false; } bool isComplexQuery(const Atom *a) { if (!a->hasQuery()) return false; // std::cerr<<"\n"<getIdx(); // negated things are always complex: if (a->getQuery()->getNegation()) return true; std::string descr = a->getQuery()->getDescription(); // std::cerr<<" "<getQuery(), hasAtNum)) return true; if (hasAtNum) return false; else return true; } return true; } bool isAtomAromatic(const Atom *a) { bool res = false; if (!a->hasQuery()) { res = a->getIsAromatic(); } else { std::string descr = a->getQuery()->getDescription(); if (descr == "AtomAtomicNum") { res = a->getIsAromatic(); } else if (descr == "AtomIsAromatic") { res = true; if (a->getQuery()->getNegation()) res = !res; } else if (descr == "AtomIsAliphatic") { res = false; if (a->getQuery()->getNegation()) res = !res; } else if (descr == "AtomAnd") { Queries::Query::CHILD_VECT_CI childIt = a->getQuery()->beginChildren(); if ((*childIt)->getDescription() == "AtomAtomicNum") { if (a->getQuery()->getNegation()) { res = false; } else if ((*(childIt + 1))->getDescription() == "AtomIsAliphatic") { res = false; } else if ((*(childIt + 1))->getDescription() == "AtomIsAromatic") { res = true; } } } } return res; } };