// // Copyright (C) 2018 Boran Adas, Google Summer of Code // // @@ 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 #include #include namespace RDKit { namespace TopologicalTorsion { using namespace AtomPairs; template TopologicalTorsionArguments::TopologicalTorsionArguments( const bool includeChirality, const uint32_t torsionAtomCount, const bool countSimulation, const std::vector countBounds, const std::uint32_t fpSize) : FingerprintArguments(countSimulation, countBounds, fpSize), df_includeChirality(includeChirality), d_torsionAtomCount(torsionAtomCount){}; template OutputType TopologicalTorsionArguments::getResultSize() const { OutputType result = 1; return (result << (d_torsionAtomCount * (codeSize + (df_includeChirality ? numChiralBits : 0)))); }; template std::string TopologicalTorsionArguments::infoString() const { return "TopologicalTorsionArguments includeChirality=" + std::to_string(df_includeChirality) + " torsionAtomCount=" + std::to_string(d_torsionAtomCount); }; template OutputType TopologicalTorsionAtomEnv::getBitId( FingerprintArguments *, // arguments const std::vector *, // atomInvariants const std::vector *, // bondInvariants const AdditionalOutput *additionalOutput, const bool, // hashResults const std::uint64_t fpSize) const { if (additionalOutput) { OutputType bitId = d_bitId; if (fpSize) { bitId %= fpSize; } if (additionalOutput->atomToBits || additionalOutput->atomCounts) { for (auto aid : d_atomPath) { if (additionalOutput->atomToBits) { additionalOutput->atomToBits->at(aid).push_back(bitId); } if (additionalOutput->atomCounts) { additionalOutput->atomCounts->at(aid)++; } } } if (additionalOutput->bitPaths) { (*additionalOutput->bitPaths)[bitId].push_back(d_atomPath); } } return d_bitId; }; template std::vector *> TopologicalTorsionEnvGenerator::getEnvironments( const ROMol &mol, FingerprintArguments *arguments, const std::vector *fromAtoms, const std::vector *ignoreAtoms, const int, // confId const AdditionalOutput *, // additionalOutput const std::vector *atomInvariants, const std::vector *, // bondInvariants const bool hashResults) const { auto *topologicalTorsionArguments = dynamic_cast *>(arguments); std::vector *> result; boost::dynamic_bitset<> *fromAtomsBV = nullptr; if (fromAtoms) { fromAtomsBV = new boost::dynamic_bitset<>(mol.getNumAtoms()); for (auto fAt : *fromAtoms) { fromAtomsBV->set(fAt); } } boost::dynamic_bitset<> *ignoreAtomsBV = nullptr; if (ignoreAtoms) { ignoreAtomsBV = new boost::dynamic_bitset<>(mol.getNumAtoms()); for (auto fAt : *ignoreAtoms) { ignoreAtomsBV->set(fAt); } } boost::dynamic_bitset<> pAtoms(mol.getNumAtoms()); PATH_LIST paths = findAllPathsOfLengthN( mol, topologicalTorsionArguments->d_torsionAtomCount, false); for (PATH_LIST::const_iterator pathIt = paths.begin(); pathIt != paths.end(); ++pathIt) { bool keepIt = true; if (fromAtomsBV) { keepIt = false; } std::vector pathCodes; const PATH_TYPE &path = *pathIt; if (fromAtomsBV) { if (fromAtomsBV->test(static_cast(path.front())) || fromAtomsBV->test(static_cast(path.back()))) { keepIt = true; } } if (keepIt && ignoreAtomsBV) { for (int pElem : path) { if (ignoreAtomsBV->test(pElem)) { keepIt = false; break; } } } if (keepIt) { pAtoms.reset(); for (auto pIt = path.begin(); pIt < path.end(); ++pIt) { // look for a cycle that doesn't start at the first atom // we can't effectively canonicalize these at the moment // (was github #811) if (pIt != path.begin() && *pIt != *(path.begin()) && pAtoms[*pIt]) { pathCodes.clear(); break; } pAtoms.set(*pIt); unsigned int code = (*atomInvariants)[*pIt] % ((1 << codeSize) - 1) + 1; // subtract off the branching number: if (pIt != path.begin() && pIt + 1 != path.end()) { --code; } pathCodes.push_back(code); } if (pathCodes.size()) { OutputType code; if (hashResults) { code = getTopologicalTorsionHash(pathCodes); } else { code = getTopologicalTorsionCode( pathCodes, topologicalTorsionArguments->df_includeChirality); } result.push_back(new TopologicalTorsionAtomEnv(code, path)); } } } delete fromAtomsBV; delete ignoreAtomsBV; return result; }; template std::string TopologicalTorsionEnvGenerator::infoString() const { return "TopologicalTorsionEnvGenerator"; }; template FingerprintGenerator *getTopologicalTorsionGenerator( const bool includeChirality, const uint32_t torsionAtomCount, AtomInvariantsGenerator *atomInvariantsGenerator, const bool countSimulation, const std::vector countBounds, const std::uint32_t fpSize, const bool ownsAtomInvGen) { auto *envGenerator = new TopologicalTorsionEnvGenerator(); auto *arguments = new TopologicalTorsionArguments( includeChirality, torsionAtomCount, countSimulation, countBounds, fpSize); bool ownsAtomInvGenerator = ownsAtomInvGen; if (!atomInvariantsGenerator) { atomInvariantsGenerator = new AtomPair::AtomPairAtomInvGenerator(includeChirality, true); ownsAtomInvGenerator = true; } return new FingerprintGenerator(envGenerator, arguments, atomInvariantsGenerator, nullptr, ownsAtomInvGenerator, false); }; // Topological torsion fingerprint does not support 32 bit output yet template RDKIT_FINGERPRINTS_EXPORT FingerprintGenerator * getTopologicalTorsionGenerator(const bool includeChirality, const uint32_t torsionAtomCount, AtomInvariantsGenerator *atomInvariantsGenerator, const bool countSimulation, const std::vector countBounds, const std::uint32_t fpSize, const bool ownsAtomInvGen); } // namespace TopologicalTorsion } // namespace RDKit