mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
423 lines
13 KiB
C++
423 lines
13 KiB
C++
// $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 <algorithm>
|
|
#include <RDGeneral/types.h>
|
|
|
|
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<unsigned int>(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<unsigned int>(firstThousandPrimes[at->getOwningMol()[*beg]->getBondType()]);
|
|
++beg;
|
|
}
|
|
for(unsigned int i=0;i<at->getTotalNumHs();i++){
|
|
prod *= static_cast<unsigned int>(firstThousandPrimes[Bond::SINGLE]);
|
|
}
|
|
return prod;
|
|
}
|
|
|
|
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomImplicitValenceQuery(int what){
|
|
ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomImplicitValence);
|
|
res->setDescription("AtomImplicitValence");
|
|
return res;
|
|
}
|
|
ATOM_EQUALS_QUERY *makeAtomExplicitValenceQuery(int what){
|
|
ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomExplicitValence);
|
|
res->setDescription("AtomExplicitValence");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomTotalValenceQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomTotalValence);
|
|
res->setDescription("AtomTotalValence");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomNumQuery(int what){
|
|
return makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomNum,"AtomAtomicNum");
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomExplicitDegreeQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomExplicitDegree);
|
|
res->setDescription("AtomExplicitDegree");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomTotalDegreeQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomTotalDegree);
|
|
res->setDescription("AtomTotalDegree");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomHCountQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomHCount);
|
|
res->setDescription("AtomHCount");
|
|
return res;
|
|
}
|
|
ATOM_EQUALS_QUERY *makeAtomImplicitHCountQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomImplicitHCount);
|
|
res->setDescription("AtomImplicitHCount");
|
|
return res;
|
|
}
|
|
ATOM_EQUALS_QUERY *makeAtomHasImplicitHQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryAtomHasImplicitH);
|
|
res->setDescription("AtomHasImplicitH");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomAromaticQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryAtomAromatic);
|
|
res->setDescription("AtomIsAromatic");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomAliphaticQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryAtomAliphatic);
|
|
res->setDescription("AtomIsAliphatic");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomUnsaturatedQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryAtomUnsaturated);
|
|
res->setDescription("AtomUnsaturated");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomMassQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(massIntegerConversionFactor*what,
|
|
queryAtomMass);
|
|
res->setDescription("AtomMass");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomIsotopeQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,
|
|
queryAtomIsotope);
|
|
res->setDescription("AtomIsotope");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomFormalChargeQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomFormalCharge);
|
|
res->setDescription("AtomFormalCharge");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomHybridizationQuery(int what){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(what,queryAtomHybridization);
|
|
res->setDescription("AtomHybridization");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomInRingQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryIsAtomInRing);
|
|
res->setDescription("AtomInRing");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomHasRingBondQuery(){
|
|
ATOM_EQUALS_QUERY *res=makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(true,queryAtomHasRingBond);
|
|
res->setDescription("AtomHasRingBond");
|
|
return res;
|
|
}
|
|
|
|
ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what){
|
|
ATOM_EQUALS_QUERY *res;
|
|
res = makeAtomSimpleQuery<ATOM_EQUALS_QUERY>(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 *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<BOND_EQUALS_QUERY *>(child->get())->getVal()!=Bond::SINGLE &&
|
|
static_cast<BOND_EQUALS_QUERY *>(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<<" |"<<descr;
|
|
if(descr=="AtomAtomicNum"){
|
|
hasAtNum=true;
|
|
return false;
|
|
}
|
|
if(descr=="AtomOr" || descr=="AtomXor") return true;
|
|
if(descr=="AtomAnd"){
|
|
Queries::Query<int,Atom const *,true>::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"<<a->getIdx();
|
|
// negated things are always complex:
|
|
if( a->getQuery()->getNegation()) return true;
|
|
std::string descr=a->getQuery()->getDescription();
|
|
//std::cerr<<" "<<descr;
|
|
if(descr=="AtomAtomicNum") return false;
|
|
if(descr=="AtomOr" || descr=="AtomXor") return true;
|
|
if(descr=="AtomAnd"){
|
|
bool hasAtNum=false;
|
|
if(_complexQueryHelper(a->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<int,Atom const *,true>::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;
|
|
}
|
|
|
|
|
|
};
|