diff --git a/Code/GraphMol/WedgeBonds.cpp b/Code/GraphMol/WedgeBonds.cpp index 92b64b354..044bdfab9 100644 --- a/Code/GraphMol/WedgeBonds.cpp +++ b/Code/GraphMol/WedgeBonds.cpp @@ -54,23 +54,11 @@ namespace detail { std::pair countChiralNbrs(const ROMol &mol, int noNbrs) { INT_VECT nChiralNbrs(mol.getNumAtoms(), noNbrs); - // start by looking for bonds that are already wedged. A wiggly bond with - // BondDir::NONE plus _UnknownStereo=1 (the state left by - // clearSingleBondDirFlags) is treated the same as one that still has - // BondDir::UNKNOWN: an intentional stereo annotation we should not overwrite. + // start by looking for bonds that are already wedged for (const auto bond : mol.bonds()) { - bool isDirected = bond->getBondDir() == Bond::BEGINWEDGE || - bond->getBondDir() == Bond::BEGINDASH || - bond->getBondDir() == Bond::UNKNOWN; - if (!isDirected) { - int unknownStereo = 0; - if (bond->getPropIfPresent(common_properties::_UnknownStereo, - unknownStereo) && - unknownStereo) { - isDirected = true; - } - } - if (isDirected) { + if (bond->getBondDir() == Bond::BEGINWEDGE || + bond->getBondDir() == Bond::BEGINDASH || + bond->getBondDir() == Bond::UNKNOWN) { if (bond->getBeginAtom()->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || bond->getBeginAtom()->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW) { nChiralNbrs[bond->getBeginAtomIdx()] = noNbrs + 1; diff --git a/Code/GraphMol/catch_chirality.cpp b/Code/GraphMol/catch_chirality.cpp index 1c68debb8..5202aeb5b 100644 --- a/Code/GraphMol/catch_chirality.cpp +++ b/Code/GraphMol/catch_chirality.cpp @@ -6554,80 +6554,3 @@ TEST_CASE( REQUIRE(m); CHECK(*labels_reference == get_bond_stereo_labels(*m)); } - -TEST_CASE( - "WedgeMolBonds does not steal a wiggly bond from an adjacent chiral " - "atom across clearSingleBondDirFlags") { - // CC[C@@H](Cl)N: atom 2 (C@@H) is the chiral center; atom 4 (N) is a - // degree-1 terminal neighbor. The existing countChiralNbrs handling for - // BondDir::UNKNOWN treats a wiggly bond as the stereo annotation for the - // adjacent chiral atom and pre-skips it. After clearSingleBondDirFlags, - // the bond's BondDir is NONE and only _UnknownStereo=1 remains as a - // marker; countChiralNbrs must recognize that marker so the same - // pre-skip behavior applies. Without this, pickBondToWedge would pick - // the wiggly bond (terminal neighbors are preferred) and the caller's - // subsequent restore of BondDir::UNKNOWN would erase the wedge, leaving - // the chiral atom with no visible stereo. - std::string smi = - "CC[C@@H](Cl)N " - "|(-2.078461,0.000000,;-0.779423,0.750000,;0.519615,-0.000000,;" - "0.519615,-1.500000,;1.818653,0.750000,)|"; - std::unique_ptr m{SmilesToMol(smi)}; - REQUIRE(m); - - auto *chiralAtom = m->getAtomWithIdx(2); - REQUIRE(chiralAtom->getChiralTag() != Atom::ChiralType::CHI_UNSPECIFIED); - const auto originalChiralTag = chiralAtom->getChiralTag(); - - // Mark the bond to N (atom 4, terminal) as a wiggly bond - auto *wigglyBond = m->getBondBetweenAtoms(2, 4); - REQUIRE(wigglyBond != nullptr); - wigglyBond->setBondDir(Bond::BondDir::UNKNOWN); - - // Simulate the typical re-wedging pattern: clearSingleBondDirFlags saves - // _UnknownStereo=1 for bonds with BondDir::UNKNOWN and then clears BondDir - // to NONE, so that stale wedge directions are removed before re-wedging. - MolOps::clearSingleBondDirFlags(*m); - REQUIRE(wigglyBond->getBondDir() == Bond::BondDir::NONE); - - Chirality::wedgeMolBonds(*m, &m->getConformer()); - - // No bond at the chiral center should be wedged: the wiggly bond is the - // intentional stereo annotation, matching the BondDir::UNKNOWN behavior - // before clearSingleBondDirFlags. - for (const auto b : m->atomBonds(chiralAtom)) { - CHECK(b->getBondDir() != Bond::BondDir::BEGINWEDGE); - CHECK(b->getBondDir() != Bond::BondDir::BEGINDASH); - } - - // Round-trip preserves the chiral tag itself; only the visual wedging - // representation is affected by the wiggly-bond annotation. - CHECK(chiralAtom->getChiralTag() == originalChiralTag); -} - -TEST_CASE( - "pickBondsToWedge respects _UnknownStereo=1 marker when called directly") { - // pickBondsToWedge is part of the public API (Chirality.h); callers can - // invoke it without going through wedgeMolBonds, so the recognition of - // the _UnknownStereo=1 marker has to live in countChiralNbrs itself. - std::string smi = - "CC[C@@H](Cl)N " - "|(-2.078461,0.000000,;-0.779423,0.750000,;0.519615,-0.000000,;" - "0.519615,-1.500000,;1.818653,0.750000,)|"; - std::unique_ptr m{SmilesToMol(smi)}; - REQUIRE(m); - - auto *wigglyBond = m->getBondBetweenAtoms(2, 4); - REQUIRE(wigglyBond != nullptr); - wigglyBond->setBondDir(Bond::BondDir::UNKNOWN); - MolOps::clearSingleBondDirFlags(*m); - REQUIRE(wigglyBond->getBondDir() == Bond::BondDir::NONE); - - auto wedgeBonds = - Chirality::pickBondsToWedge(*m, nullptr, &m->getConformer()); - - // The chiral atom's stereo is already expressed by the wiggly bond, so - // pickBondsToWedge must not pick any bond to wedge for it. The molecule - // has no atropisomers, so the returned map should be empty. - CHECK(wedgeBonds.empty()); -}