bool bondCompat(const BOND_SPTR &b1, const BOND_SPTR &b2, bool useQueryQueryMatches) { PRECONDITION(b1, "bad bond"); PRECONDITION(b2, "bad bond"); bool res; if (useQueryQueryMatches && b1->hasQuery() && b2->hasQuery()) { res = static_cast<QueryBond *>(b1.get())->QueryMatch( static_cast<QueryBond *>(b2.get())); } else { res = b1->Match(b2); } if (res && b1->getBondType() == Bond::DATIVE && b2->getBondType() == Bond::DATIVE) { // for dative bonds we need to make sure that the direction also matches: if (!b1->getBeginAtom()->Match(b1->getBeginAtom()) || !b1->getEndAtom()->Match(b2->getEndAtom())) { res = false; } } // std::cout << "\t\tbondCompat: "<< b1->getIdx() << "-" << b2->getIdx() << ": // " << res << std::endl; return res; }
RWMOL_SPTR initProduct(const ROMOL_SPTR prodTemplateSptr) { const ROMol *prodTemplate=prodTemplateSptr.get(); RWMol *res=new RWMol(); // --------- --------- --------- --------- --------- --------- // Initialize by making a copy of the product template as a normal molecule. // NOTE that we can't just use a normal copy because we do not want to end up // with query atoms or bonds in the product. // copy in the atoms: ROMol::ATOM_ITER_PAIR atItP = prodTemplate->getVertices(); while(atItP.first != atItP.second ) { Atom *oAtom=(*prodTemplate)[*(atItP.first++)].get(); Atom *newAtom=new Atom(*oAtom); res->addAtom(newAtom,false,true); int mapNum; if(newAtom->getPropIfPresent(common_properties::molAtomMapNumber, mapNum)) { // set bookmarks for the mapped atoms: res->setAtomBookmark(newAtom,mapNum); // now clear the molAtomMapNumber property so that it doesn't // end up in the products (this was bug 3140490): newAtom->clearProp(common_properties::molAtomMapNumber); } newAtom->setChiralTag(Atom::CHI_UNSPECIFIED); // if the product-template atom has the inversion flag set // to 4 (=SET), then bring its stereochem over, otherwise we'll // ignore it: int iFlag; if(oAtom->getPropIfPresent(common_properties::molInversionFlag, iFlag)) { if(iFlag==4) newAtom->setChiralTag(oAtom->getChiralTag()); } // check for properties we need to set: int val; if(newAtom->getPropIfPresent(common_properties::_QueryFormalCharge, val)) { newAtom->setFormalCharge(val); } if(newAtom->getPropIfPresent(common_properties::_QueryHCount, val)) { newAtom->setNumExplicitHs(val); } if(newAtom->getPropIfPresent(common_properties::_QueryMass, val)) { // FIX: technically should do something with this //newAtom->setMass(val); } if(newAtom->getPropIfPresent(common_properties::_QueryIsotope, val)) { newAtom->setIsotope(val); } } // and the bonds: ROMol::BOND_ITER_PAIR bondItP = prodTemplate->getEdges(); while(bondItP.first != bondItP.second ) { const BOND_SPTR oldB=(*prodTemplate)[*(bondItP.first++)]; unsigned int bondIdx; bondIdx=res->addBond(oldB->getBeginAtomIdx(),oldB->getEndAtomIdx(),oldB->getBondType())-1; // make sure we don't lose the bond dir information: Bond *newB=res->getBondWithIdx(bondIdx); newB->setBondDir(oldB->getBondDir()); // Special case/hack: // The product has been processed by the SMARTS parser. // The SMARTS parser tags unspecified bonds as single, but then adds // a query so that they match single or double // This caused Issue 1748846 // http://sourceforge.net/tracker/index.php?func=detail&aid=1748846&group_id=160139&atid=814650 // We need to fix that little problem now: if( oldB->hasQuery()) { // remember that the product has been processed by the SMARTS parser. std::string queryDescription=oldB->getQuery()->getDescription(); if(queryDescription=="BondOr" && oldB->getBondType()==Bond::SINGLE) { // We need to fix that little problem now: if(newB->getBeginAtom()->getIsAromatic() && newB->getEndAtom()->getIsAromatic()) { newB->setBondType(Bond::AROMATIC); newB->setIsAromatic(true); } else { newB->setBondType(Bond::SINGLE); newB->setIsAromatic(false); } } else if(queryDescription=="BondNull") { newB->setProp(common_properties::NullBond,1); } } } return RWMOL_SPTR(res); } // end of initProduct()