bool atomIsCandidateForRingStereochem(const ROMol &mol, const Atom *atom) { PRECONDITION(atom, "bad atom"); bool res = false; if (!atom->getPropIfPresent(common_properties::_ringStereochemCand, res)) { const RingInfo *ringInfo = mol.getRingInfo(); if (ringInfo->isInitialized() && ringInfo->numAtomRings(atom->getIdx())) { ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = mol.getAtomBonds(atom); std::vector<const Atom *> nonRingNbrs; std::vector<const Atom *> ringNbrs; while (beg != end) { const BOND_SPTR bond = mol[*beg]; if (!ringInfo->numBondRings(bond->getIdx())) { nonRingNbrs.push_back(bond->getOtherAtom(atom)); } else { ringNbrs.push_back(bond->getOtherAtom(atom)); } ++beg; } unsigned int rank1 = 0, rank2 = 0; switch (nonRingNbrs.size()) { case 0: // don't do spiro: res = false; break; case 1: if (ringNbrs.size() == 2) res = true; break; case 2: if (nonRingNbrs[0]->getPropIfPresent(common_properties::_CIPRank, rank1) && nonRingNbrs[1]->getPropIfPresent(common_properties::_CIPRank, rank2)) { if (rank1 == rank2) { res = false; } else { res = true; } } break; default: res = false; } } atom->setProp(common_properties::_ringStereochemCand, res, 1); } return res; }
// find the neighbors for an atoms that are not connected by single bond that is // not refBond // if checkDir is true only neighbor atoms with bonds marked with a direction // will be returned void findAtomNeighborsHelper(const ROMol &mol, const Atom *atom, const Bond *refBond, UINT_VECT &neighbors, bool checkDir = false) { PRECONDITION(atom, "bad atom"); PRECONDITION(refBond, "bad bond"); neighbors.clear(); ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = mol.getAtomBonds(atom); while (beg != end) { const BOND_SPTR bond = mol[*beg]; Bond::BondDir dir = bond->getBondDir(); if (bond->getBondType() == Bond::SINGLE && bond->getIdx() != refBond->getIdx()) { if (checkDir) { if ((dir != Bond::ENDDOWNRIGHT) && (dir != Bond::ENDUPRIGHT)) { ++beg; continue; } } Atom *nbrAtom = bond->getOtherAtom(atom); neighbors.push_back(nbrAtom->getIdx()); } ++beg; } }
// construct a vector with <atomIdx,direction> pairs for // neighbors of a given atom. This list will only be // non-empty if at least one of the bonds has its direction // set. void findAtomNeighborDirHelper(const ROMol &mol, const Atom *atom, const Bond *refBond, UINT_VECT &ranks, INT_PAIR_VECT &neighbors, bool &hasExplicitUnknownStereo) { PRECONDITION(atom, "bad atom"); PRECONDITION(refBond, "bad bond"); bool seenDir = false; ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = mol.getAtomBonds(atom); while (beg != end) { const BOND_SPTR bond = mol[*beg]; // check whether this bond is explictly set to have unknown stereo if (!hasExplicitUnknownStereo) { int explicit_unknown_stereo; if (bond->getBondDir() == Bond::UNKNOWN // there's a squiggle bond || (bond->getPropIfPresent<int>(common_properties::_UnknownStereo, explicit_unknown_stereo) && explicit_unknown_stereo)) hasExplicitUnknownStereo = true; } Bond::BondDir dir = bond->getBondDir(); if (bond->getIdx() != refBond->getIdx()) { if (dir == Bond::ENDDOWNRIGHT || dir == Bond::ENDUPRIGHT) { seenDir = true; // If we're considering the bond "backwards", (i.e. from end // to beginning, reverse the effective direction: if (atom != bond->getBeginAtom()) { if (dir == Bond::ENDDOWNRIGHT) dir = Bond::ENDUPRIGHT; else dir = Bond::ENDDOWNRIGHT; } } Atom *nbrAtom = bond->getOtherAtom(atom); neighbors.push_back(std::make_pair(nbrAtom->getIdx(), dir)); } ++beg; } if (!seenDir) { neighbors.clear(); } else { if (neighbors.size() == 2 && ranks[neighbors[0].first] == ranks[neighbors[1].first]) { // the two substituents are identical, no stereochemistry here: neighbors.clear(); } else { // it's possible that direction was set only one of the bonds, set the // other // bond's direction to be reversed: if (neighbors[0].second != Bond::ENDDOWNRIGHT && neighbors[0].second != Bond::ENDUPRIGHT) { CHECK_INVARIANT(neighbors.size() > 1, "too few neighbors"); neighbors[0].second = neighbors[1].second == Bond::ENDDOWNRIGHT ? Bond::ENDUPRIGHT : Bond::ENDDOWNRIGHT; } else if (neighbors.size() > 1 && neighbors[1].second != Bond::ENDDOWNRIGHT && neighbors[1].second != Bond::ENDUPRIGHT) { neighbors[1].second = neighbors[0].second == Bond::ENDDOWNRIGHT ? Bond::ENDUPRIGHT : Bond::ENDDOWNRIGHT; } } } }