double getAlignmentTransform(const ROMol &prbMol, const ROMol &refMol, RDGeom::Transform3D &trans, int prbCid, int refCid, const MatchVectType *atomMap, const RDNumeric::DoubleVector *weights, bool reflect, unsigned int maxIterations) { RDGeom::Point3DConstPtrVect refPoints, prbPoints; const Conformer &prbCnf = prbMol.getConformer(prbCid); const Conformer &refCnf = refMol.getConformer(refCid); if (atomMap == 0) { // we have to figure out the mapping between the two molecule MatchVectType match; if (SubstructMatch(refMol, prbMol, match)) { MatchVectType::const_iterator mi; for (mi = match.begin(); mi != match.end(); mi++) { prbPoints.push_back(&prbCnf.getAtomPos(mi->first)); refPoints.push_back(&refCnf.getAtomPos(mi->second)); } } else { throw MolAlignException("No sub-structure match found between the probe and query mol"); } } else { MatchVectType::const_iterator mi; for (mi = atomMap->begin(); mi != atomMap->end(); mi++) { prbPoints.push_back(&prbCnf.getAtomPos(mi->first)); refPoints.push_back(&refCnf.getAtomPos(mi->second)); } } double ssr = RDNumeric::Alignments::AlignPoints(refPoints, prbPoints, trans, weights, reflect, maxIterations); ssr /= (prbPoints.size()); return sqrt(ssr); }
ROMol *prepareMol(const ROMol &mol, const FragCatParams *fparams, MatchVectType &aToFmap) { PRECONDITION(fparams,""); // get a mapping of the functional groups onto the molecule INT_VECT fgBonds; MatchVectType aidToFid = findFuncGroupsOnMol(mol, fparams, fgBonds); // get the core piece of molecule (i.e. the part of the molecule // without the functional groups). This basically the part of the molecule // that does not contain the function group bonds given by "fgBonds" INT_VECT cBonds; int bid, nbds = mol.getNumBonds(); for (bid = 0; bid < nbds; bid++) { if (std::find(fgBonds.begin(), fgBonds.end(), bid) == fgBonds.end()) { cBonds.push_back(bid); } } INT_MAP_INT aIdxMap; // a map from atom id in mol to the new atoms id in coreMol ROMol *coreMol = Subgraphs::pathToSubmol(mol, cBonds, false, aIdxMap); // now map the functional groups on mol to coreMol using aIdxMap MatchVectType::iterator mati; int newID; for (mati = aidToFid.begin(); mati != aidToFid.end(); mati++) { newID = aIdxMap[mati->first]; aToFmap.push_back(std::pair<int, int>(newID, mati->second)); } return coreMol; }
//************************************************************************************* // // Adds 2D coordinates to a molecule using the Depict.dll // // ARGUMENTS: // mol: the molecule to be altered // tempFilename: (OPTIONAL) the name of the temporary file // // RETURNS: // 1 on success, 0 otherwise // // Here's the process by which this works (it's kind of contorted): // 1) convert the mol to SMILES // 2) use the DLL to convert the SMILES to a mol file (on disk) // 3) parse the mol file into a temporary molecule // 4) do a substructure match from the old molecule to the // temp one (which may have a different atom numbering or additional // atoms added). // 5) Update the positions of the atoms on the old molecule. // 6) Free the temp molecule. // // NOTES: // - *FIX:* at the moment we're not doing anything to clear up the // temp file created in this process. It'll always have the same // name unless the user explicitly asks that we do something different. // - To use the DLL, it's essential that the COMBICHEM_ROOT and COMBICHEM_RELEASE // environment variables be set. If this isn't done, this whole process // will fail. // - See the notes above about failures when opening the DLL. // //************************************************************************************* int Add2DCoordsToMolDLL(ROMol &mol,std::string tempFilename){ std::string smi=MolToSmiles(mol,true); int tmp = SmilesToMolFileDLL(smi,tempFilename); int res = -1; if(tmp){ // build another mol from that mol file: RWMol *tmpMol = MolFileToMol(tempFilename,false); // match it up with the starting mol: // (We need to do this because the depict.dll conversion // to a mol file may have added Hs) MatchVectType matchVect; bool hasMatch=SubstructMatch(tmpMol,&mol,matchVect); if(hasMatch){ const Conformer &conf = tmpMol->getCoformer(0); Coformer *nconf = new Coformer(mol.getNumAtoms()); for(MatchVectType::const_iterator mvi=matchVect.begin(); mvi!=matchVect.end();mvi++){ nconf->setAtomPos(conf.getAtomPos(mvi->first)); } confId = (int)mol.addConformer(nconf, true); } delete tmpMol; } return res; }
bool StructCheckTautomer::applyTautomer(unsigned it) { if (Options.FromTautomer.size() <= it || Options.ToTautomer.size() <= it) { if (Options.Verbose) BOOST_LOG(rdInfoLog) << "ERROR: incorrect Tautomer index it=" << it << "\n"; return false; } const ROMol &fromTautomer = *Options.FromTautomer[it]; const ROMol &toTautomer = *Options.ToTautomer[it]; if (toTautomer.getNumAtoms() != fromTautomer.getNumAtoms()) { if (Options.Verbose) BOOST_LOG(rdInfoLog) << "ERROR: incorrect data toTautomer.getNumAtoms() " "!= fromTautomer.getNumAtoms()\n"; // incorrect data // throw(.....); return false; } const unsigned nta = toTautomer.getNumAtoms(); const unsigned ntb = toTautomer.getNumBonds(); MatchVectType match; // The format is (queryAtomIdx, molAtomIdx) std::vector<unsigned> atomIdxMap( Mol.getNumAtoms()); // matched tau atom indeces if (!SubstructMatch(Mol, *Options.FromTautomer[it], match)) // SSMatch(mp, from_tautomer, SINGLE_MATCH); return false; if (Options.Verbose) BOOST_LOG(rdInfoLog) << "found match for from_tautomer with " << nta << " atoms\n"; // init for (unsigned i = 0; i < Mol.getNumAtoms(); i++) atomIdxMap[i] = -1; for (MatchVectType::const_iterator mit = match.begin(); mit != match.end(); mit++) { unsigned tai = mit->first; // From and To Tautomer Atom index unsigned mai = mit->second; // Mol Atom index atomIdxMap[mai] = tai; } // scan for completely mapped bonds and replace bond order with mapped bond // from to_tautomer for (RDKit::BondIterator_ bond = Mol.beginBonds(); bond != Mol.endBonds(); bond++) { unsigned ti = atomIdxMap[(*bond)->getBeginAtomIdx()]; unsigned tj = atomIdxMap[(*bond)->getEndAtomIdx()]; if (-1 == ti || -1 == tj) continue; const Bond *tb = toTautomer.getBondBetweenAtoms(ti, tj); if (tb && (*bond)->getBondType() != tb->getBondType()) { (*bond)->setBondType(tb->getBondType()); } } // apply charge/radical fixes if any for (unsigned i = 0; i < match.size(); i++) { Atom &atom = *Mol.getAtomWithIdx(match[i].second); const Atom &ta = *toTautomer.getAtomWithIdx(match[i].first); atom.setFormalCharge(ta.getFormalCharge()); atom.setNumRadicalElectrons(ta.getNumRadicalElectrons()); } return true; }