Ejemplo n.º 1
0
void setNewProductBond(const Bond &origB, RWMOL_SPTR product,
                       unsigned bondBeginIdx, unsigned bondEndIdx) {
  unsigned bondIdx =
      product->addBond(bondBeginIdx, bondEndIdx, origB.getBondType()) - 1;
  Bond *newB = product->getBondWithIdx(bondIdx);
  newB->setBondDir(origB.getBondDir());
}
Ejemplo n.º 2
0
void StandardPDBResidueBondOrders(RWMol *mol)
{
  RWMol::BondIterator bondIt;
  for (bondIt=mol->beginBonds(); bondIt!=mol->endBonds(); ++bondIt) {
    Bond *bond = *bondIt;
    if (bond->getBondType() == Bond::SINGLE) {
      Atom *beg = bond->getBeginAtom();
      Atom *end = bond->getEndAtom();
      if (StandardPDBDoubleBond(mol,beg,end))
        bond->setBondType(Bond::DOUBLE);
    }
  }
}
Ejemplo n.º 3
0
void WedgeMolBonds(ROMol &mol, const Conformer *conf) {
    PRECONDITION(conf, "no conformer");
    INT_MAP_INT wedgeBonds = pickBondsToWedge(mol);
    for (ROMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds();
            ++bondIt) {
        Bond *bond = *bondIt;
        if (bond->getBondType() == Bond::SINGLE) {
            Bond::BondDir dir = DetermineBondWedgeState(bond, wedgeBonds, conf);
            if (dir == Bond::BEGINWEDGE || dir == Bond::BEGINDASH) {
                bond->setBondDir(dir);
            }
        }
    }
}
Ejemplo n.º 4
0
void updateDoubleBondNeighbors(ROMol &mol, Bond *dblBond, const Conformer *conf,
                               boost::dynamic_bitset<> &needsDir,
                               std::vector<unsigned int> &singleBondCounts) {
    // we want to deal only with double bonds:
    PRECONDITION(dblBond, "bad bond");
    PRECONDITION(dblBond->getBondType() == Bond::DOUBLE, "not a double bond");
    PRECONDITION(conf, "no conformer");

#if 0
    std::cerr << "**********************\n";
    std::cerr << "**********************\n";
    std::cerr << "**********************\n";
    std::cerr << "UDBN: "<<dblBond->getIdx()<<"\n";
#endif

    ROMol::OEDGE_ITER beg, end;

    Bond *bond1 = 0, *obond1 = 0;
    boost::tie(beg, end) = mol.getAtomBonds(dblBond->getBeginAtom());
    while (beg != end) {
        Bond *tBond = mol[*beg].get();
        if (tBond->getBondType() == Bond::SINGLE ||
                tBond->getBondType() == Bond::AROMATIC) {
            // prefer bonds that already have their directionality set
            // or that are adjacent to more double bonds:
            if (!bond1) {
                bond1 = tBond;
            } else if (needsDir[tBond->getIdx()]) {
                if (singleBondCounts[tBond->getIdx()] >
                        singleBondCounts[bond1->getIdx()]) {
                    obond1 = bond1;
                    bond1 = tBond;
                } else {
                    obond1 = tBond;
                }
            } else {
                obond1 = bond1;
                bond1 = tBond;
            }
        }
        ++beg;
    }
    if (!bond1) {
        // no single bonds from the beginning atom, mark
        // the double bond as directionless and return:
        dblBond->setBondDir(Bond::EITHERDOUBLE);
        return;
    }

    Bond *bond2 = 0, *obond2 = 0;
    boost::tie(beg, end) = mol.getAtomBonds(dblBond->getEndAtom());
    while (beg != end) {
        Bond *tBond = mol[*beg].get();
        if (tBond->getBondType() == Bond::SINGLE ||
                tBond->getBondType() == Bond::AROMATIC) {
            if (!bond2) {
                bond2 = tBond;
            } else if (needsDir[tBond->getIdx()]) {
                if (singleBondCounts[tBond->getIdx()] >
                        singleBondCounts[bond2->getIdx()]) {
                    obond2 = bond2;
                    bond2 = tBond;
                } else {
                    obond2 = tBond;
                }
            } else {
                // we already had a bond2 and we don't need to set the direction
                // on the new one, so swap.
                obond2 = bond2;
                bond2 = tBond;
            }
        }
        ++beg;
    }
    if (!bond2) {
        dblBond->setBondDir(Bond::EITHERDOUBLE);
        return;
    }

    CHECK_INVARIANT(bond1 && bond2, "no bonds found");
    RDGeom::Point3D beginP = conf->getAtomPos(dblBond->getBeginAtomIdx());
    RDGeom::Point3D endP = conf->getAtomPos(dblBond->getEndAtomIdx());
    RDGeom::Point3D bond1P =
        conf->getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx()));
    RDGeom::Point3D bond2P =
        conf->getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx()));
    // check for a linear arrangement of atoms on either end:
    bool linear = false;
    RDGeom::Point3D p1;
    RDGeom::Point3D p2;
    p1 = bond1P - beginP;
    p2 = endP - beginP;
    if (isLinearArrangement(p1, p2)) {
        if (!obond1) {
            linear = true;
        } else {
            // one of the bonds was linear; what about the other one?
            Bond *tBond = bond1;
            bond1 = obond1;
            obond1 = tBond;
            bond1P =
                conf->getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx()));
            p1 = bond1P - beginP;
            if (isLinearArrangement(p1, p2)) {
                linear = true;
            }
        }
    }
    if (!linear) {
        p1 = bond2P - endP;
        p2 = beginP - endP;
        if (isLinearArrangement(p1, p2)) {
            if (!obond2) {
                linear = true;
            } else {
                Bond *tBond = bond2;
                bond2 = obond2;
                obond2 = tBond;
                bond2P =
                    conf->getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx()));
                p1 = bond2P - beginP;
                if (isLinearArrangement(p1, p2)) {
                    linear = true;
                }
            }
        }
    }
    if (linear) {
        dblBond->setBondDir(Bond::EITHERDOUBLE);
        return;
    }

    double ang = RDGeom::computeDihedralAngle(bond1P, beginP, endP, bond2P);
    bool sameTorsionDir;
    if (ang < M_PI / 2) {
        sameTorsionDir = false;
    } else {
        sameTorsionDir = true;
    }
    // std::cerr << "   angle: "<<ang<<" sameTorsionDir: " <<sameTorsionDir<<"\n";

    /*
       Time for some clarificatory text, because this gets really
       confusing really fast.

       The dihedral angle analysis above is based on viewing things
       with an atom order as follows:

       1
        \
         2 = 3
              \
               4

       so dihedrals > 90 correspond to sameDir=true

       however, the stereochemistry representation is
       based on something more like this:

       2
        \
         1 = 3
              \
               4
       (i.e. we consider the direction-setting single bonds to be
        starting at the double-bonded atom)

    */
    bool reverseBondDir = sameTorsionDir;

    Atom *atom1 = dblBond->getBeginAtom(), *atom2 = dblBond->getEndAtom();
    if (!needsDir[bond1->getIdx()]) {
        if (!needsDir[bond2->getIdx()]) {
            // check that we agree
        } else {
            if (bond1->getBeginAtom() != atom1) {
                reverseBondDir = !reverseBondDir;
            }
            setBondDirRelativeToAtom(bond2, atom2, bond1->getBondDir(),
                                     reverseBondDir, needsDir);
        }
    } else if (!needsDir[bond2->getIdx()]) {
        if (bond2->getBeginAtom() != atom2) {
            reverseBondDir = !reverseBondDir;
        }
        setBondDirRelativeToAtom(bond1, atom1, bond2->getBondDir(), reverseBondDir,
                                 needsDir);
    } else {
        setBondDirRelativeToAtom(bond1, atom1, Bond::ENDDOWNRIGHT, false, needsDir);
        setBondDirRelativeToAtom(bond2, atom2, Bond::ENDDOWNRIGHT, reverseBondDir,
                                 needsDir);
    }
    needsDir[bond1->getIdx()] = 0;
    needsDir[bond2->getIdx()] = 0;
    if (obond1 && needsDir[obond1->getIdx()]) {
        setBondDirRelativeToAtom(obond1, atom1, bond1->getBondDir(),
                                 bond1->getBeginAtom() == atom1, needsDir);
        needsDir[obond1->getIdx()] = 0;
    }
    if (obond2 && needsDir[obond2->getIdx()]) {
        setBondDirRelativeToAtom(obond2, atom2, bond2->getBondDir(),
                                 bond2->getBeginAtom() == atom2, needsDir);
        needsDir[obond2->getIdx()] = 0;
    }
#if 0
    std::cerr << "  1:"<<bond1->getIdx()<<" ";
    if(obond1) std::cerr<<obond1->getIdx()<<std::endl;
    else  std::cerr<<"N/A"<<std::endl;
    std::cerr << "  2:"<<bond2->getIdx()<<" ";
    if(obond2) std::cerr<<obond2->getIdx()<<std::endl;
    else  std::cerr<<"N/A"<<std::endl;
    std::cerr << "**********************\n";
    std::cerr << "**********************\n";
    std::cerr << "**********************\n";
#endif
}
Ejemplo n.º 5
0
// finds cycles
void dfsFindCycles(ROMol &mol, int atomIdx, int inBondIdx,
                   std::vector<AtomColors> &colors, const UINT_VECT &ranks,
                   INT_VECT &atomOrders, VECT_INT_VECT &atomRingClosures,
                   const boost::dynamic_bitset<> *bondsInPlay,
                   const std::vector<std::string> *bondSymbols, bool doRandom) {
  Atom *atom = mol.getAtomWithIdx(atomIdx);
  atomOrders.push_back(atomIdx);

  colors[atomIdx] = GREY_NODE;

  // ---------------------
  //
  //  Build the list of possible destinations from here
  //
  // ---------------------
  std::vector<PossibleType> possibles;
  possibles.resize(0);
  ROMol::OBOND_ITER_PAIR bondsPair = mol.getAtomBonds(atom);
  possibles.reserve(bondsPair.second - bondsPair.first);

  while (bondsPair.first != bondsPair.second) {
    Bond *theBond = mol[*(bondsPair.first)];
    bondsPair.first++;
    if (bondsInPlay && !(*bondsInPlay)[theBond->getIdx()]) continue;
    if (inBondIdx < 0 ||
        theBond->getIdx() != static_cast<unsigned int>(inBondIdx)) {
      int otherIdx = theBond->getOtherAtomIdx(atomIdx);
      long rank = ranks[otherIdx];
      // ---------------------
      //
      // things are a bit more complicated if we are sitting on a
      // ring atom. we would like to traverse first to the
      // ring-closure atoms, then to atoms outside the ring first,
      // then to atoms in the ring that haven't already been visited
      // (non-ring-closure atoms).
      //
      //  Here's how the black magic works:
      //   - non-ring atom neighbors have their original ranks
      //   - ring atom neighbors have this added to their ranks:
      //       (MAX_BONDTYPE - bondOrder)*MAX_NATOMS*MAX_NATOMS
      //   - ring-closure neighbors lose a factor of:
      //       (MAX_BONDTYPE+1)*MAX_NATOMS*MAX_NATOMS
      //
      //  This tactic biases us to traverse to non-ring neighbors first,
      //  original ordering if bond orders are all equal... crafty, neh?
      //
      // ---------------------
      if (!doRandom) {
        if (colors[otherIdx] == GREY_NODE) {
          rank -= static_cast<int>(MAX_BONDTYPE + 1) * MAX_NATOMS * MAX_NATOMS;
          if (!bondSymbols) {
            rank += static_cast<int>(MAX_BONDTYPE - theBond->getBondType()) *
                    MAX_NATOMS;
          } else {
            const std::string &symb = (*bondSymbols)[theBond->getIdx()];
            std::uint32_t hsh = gboost::hash_range(symb.begin(), symb.end());
            rank += (hsh % MAX_NATOMS) * MAX_NATOMS;
          }
        } else if (theBond->getOwningMol().getRingInfo()->numBondRings(
                       theBond->getIdx())) {
          if (!bondSymbols) {
            rank += static_cast<int>(MAX_BONDTYPE - theBond->getBondType()) *
                    MAX_NATOMS * MAX_NATOMS;
          } else {
            const std::string &symb = (*bondSymbols)[theBond->getIdx()];
            std::uint32_t hsh = gboost::hash_range(symb.begin(), symb.end());
            rank += (hsh % MAX_NATOMS) * MAX_NATOMS * MAX_NATOMS;
          }
        }
      } else {
        // randomize the rank
        rank = std::rand();
      }
      // std::cerr << "            " << atomIdx << ": " << otherIdx << " " <<
      // rank
      //           << std::endl;
      // std::cerr<<"aIdx: "<< atomIdx <<"   p: "<<otherIdx<<" Rank:
      // "<<ranks[otherIdx] <<" "<<colors[otherIdx]<<"
      // "<<theBond->getBondType()<<" "<<rank<<std::endl;
      possibles.push_back(PossibleType(rank, otherIdx, theBond));
    }
  }

  // ---------------------
  //
  //  Sort on ranks
  //
  // ---------------------
  std::sort(possibles.begin(), possibles.end(), _possibleCompare());
  // if (possibles.size())
  //   std::cerr << " aIdx1: " << atomIdx
  //             << " first: " << possibles.front().get<0>() << " "
  //             << possibles.front().get<1>() << std::endl;
  // // ---------------------
  //
  //  Now work the children
  //
  // ---------------------
  for (auto &possible : possibles) {
    int possibleIdx = possible.get<1>();
    Bond *bond = possible.get<2>();
    switch (colors[possibleIdx]) {
      case WHITE_NODE:
        // -----
        // we haven't seen this node at all before, traverse
        // -----
        dfsFindCycles(mol, possibleIdx, bond->getIdx(), colors, ranks,
                      atomOrders, atomRingClosures, bondsInPlay, bondSymbols,
                      doRandom);
        break;
      case GREY_NODE:
        // -----
        // we've seen this, but haven't finished it (we're finishing a ring)
        // -----
        atomRingClosures[possibleIdx].push_back(bond->getIdx());
        atomRingClosures[atomIdx].push_back(bond->getIdx());
        break;
      default:
        // -----
        // this node has been finished. don't do anything.
        // -----
        break;
    }
  }
  colors[atomIdx] = BLACK_NODE;
}  // namespace Canon