// // Copyright (C) 2018 Susan H. Leung // // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license // which is included in the file license.txt, found at the root // of the RDKit source tree. // #include "Normalize.h" #include #include #include #include #include #include #include using namespace std; using namespace RDKit; namespace RDKit { class RWMol; class ROMol; namespace MolStandardize { // unsigned int MAX_RESTARTS = 200; // constructor Normalizer::Normalizer() { BOOST_LOG(rdInfoLog) << "Initializing Normalizer\n"; TransformCatalogParams tparams(defaultCleanupParameters.normalizations); // unsigned int ntransforms = tparams->getNumTransformations(); // TEST_ASSERT(ntransforms == 22); this->d_tcat = new TransformCatalog(&tparams); this->MAX_RESTARTS = 200; } // overloaded constructor Normalizer::Normalizer(const std::string normalizeFile, const unsigned int maxRestarts) { BOOST_LOG(rdInfoLog) << "Initializing Normalizer\n"; TransformCatalogParams tparams(normalizeFile); this->d_tcat = new TransformCatalog(&tparams); this->MAX_RESTARTS = maxRestarts; } // destructor Normalizer::~Normalizer() { delete d_tcat; } ROMol *Normalizer::normalize(const ROMol &mol) { BOOST_LOG(rdInfoLog) << "Running Normalizer\n"; PRECONDITION(this->d_tcat, ""); const TransformCatalogParams *tparams = this->d_tcat->getCatalogParams(); PRECONDITION(tparams, ""); const std::vector> &transforms = tparams->getTransformations(); std::vector> frags = MolOps::getMolFrags(mol); std::vector nfrags; //( frags.size() ); for (const auto &frag : frags) { ROMOL_SPTR nfrag(this->normalizeFragment(*frag, transforms)); nfrags.push_back(nfrag); } ROMol *outmol = new ROMol(*(nfrags.back())); nfrags.pop_back(); for (const auto &nfrag : nfrags) { ROMol *tmol = combineMols(*outmol, *nfrag); delete outmol; outmol = tmol; // delete nfrag; } return outmol; } ROMol *Normalizer::normalizeFragment( const ROMol &mol, const std::vector> &transforms) { ROMol *nfrag = new ROMol(mol); for (unsigned int i = 0; i < MAX_RESTARTS; ++i) { bool loop_brake = false; // Iterate through Normalization transforms and apply each in order for (auto &transform : transforms) { std::string tname; transform->getProp(common_properties::_Name, tname); boost::shared_ptr product = this->applyTransform(*nfrag, *transform); if (product != nullptr) { BOOST_LOG(rdInfoLog) << "Rule applied: " << tname << "\n"; delete nfrag; nfrag = new ROMol(*product); loop_brake = true; break; } } // For loop finishes normally, all applicable transforms have been applied if (!loop_brake) { return nfrag; } } BOOST_LOG(rdInfoLog) << "Gave up normalization after " << MAX_RESTARTS << " restarts.\n"; return nfrag; } boost::shared_ptr Normalizer::applyTransform( const ROMol &mol, ChemicalReaction &transform) { // Repeatedly apply normalization transform to molecule until no changes // occur. // // It is possible for multiple products to be produced when a rule is applied. // The rule is applied repeatedly to each of the products, until no further // changes occur or after 20 attempts. // // If there are multiple unique products after the final application, the // first product (sorted alphabetically by SMILES) is chosen. boost::shared_ptr tmp(new ROMol(mol)); MOL_SPTR_VECT mols; mols.push_back(tmp); transform.initReactantMatchers(); // REVIEW: what's the source of the 20 in the next line? for (unsigned int i = 0; i < 20; ++i) { std::vector pdts; for (auto &m : mols) { std::vector products = transform.runReactants({m}); for (auto &pdt : products) { // shared_ptr p0( new RWMol(*pdt[0]) ); // std::cout << MolToSmiles(*p0) << // std::endl; unsigned int failed; try { MolOps::sanitizeMol(*static_cast(pdt[0].get()), failed); Normalizer::Product np(MolToSmiles(*pdt[0]), pdt[0]); pdts.push_back(np); } catch (MolSanitizeException &) { BOOST_LOG(rdInfoLog) << "FAILED sanitizeMol.\n"; } } } if (pdts.size() != 0) { std::sort(pdts.begin(), pdts.end()); mols.clear(); for (const auto &pdt : pdts) { mols.push_back(pdt.Mol); } } else { if (i > 0) { return mols[0]; } else { return nullptr; } } } if (mols.size()) return mols[0]; else return nullptr; } } // namespace MolStandardize } // namespace RDKit