// // Copyright (C) 2016-2022 Novartis Institutes for BioMedical Research and // other RDKit contributors // // @@ 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 "../../RDGeneral/types.h" #include "../../Geometry/point.h" #include "Utilites.h" #include #include namespace RDKit { namespace StructureCheck { void SetupNeighbourhood(const ROMol &mol, std::vector &neighbours) { neighbours.clear(); neighbours.resize(mol.getNumAtoms()); for (unsigned i = 0; i < mol.getNumBonds(); i++) { const Bond *bond = mol.getBondWithIdx(i); unsigned a1 = bond->getBeginAtomIdx(); unsigned a2 = bond->getEndAtomIdx(); neighbours[a1].Atoms.push_back(a2); neighbours[a1].Bonds.push_back(i); neighbours[a2].Atoms.push_back(a1); neighbours[a2].Bonds.push_back(i); } } bool getMolAtomPoints(const ROMol &mol, std::vector &atomPoint, bool twod) { bool non_zero_z = false; atomPoint.resize(mol.getNumAtoms()); // take X,Y,Z coordinates of each atom if (0 != mol.getNumConformers()) for (auto cnfi = mol.beginConformers(); cnfi != mol.endConformers(); cnfi++) { const Conformer &conf = **cnfi; // mol.getConformer(confId); if (twod || conf.is3D()) { for (unsigned i = 0; i < mol.getNumAtoms(); i++) { atomPoint[i] = conf.getAtomPos(i); if (fabs(atomPoint[i].z) >= 1.e-7) non_zero_z = true; } break; } } if (atomPoint.empty()) { // compute XYZ // TODO: // ???? .......... } return non_zero_z; } typedef std::tuple NbrData; bool lessTuple(const NbrData &left, const NbrData &right) { if (std::get<0>(left) < std::get<0>(right)) return true; if (std::get<0>(left) > std::get<0>(right)) return false; if (std::get<1>(left) < std::get<1>(right)) return true; if (std::get<1>(left) > std::get<1>(right)) return false; if (std::get<2>(left) < std::get<2>(right)) return true; if (std::get<2>(left) > std::get<2>(right)) return false; if (std::get<3>(left) < std::get<3>(right)) return true; return false; } std::string LogNeighbourhood( const ROMol &mol, unsigned int idx, const std::vector &neighbour_array) { std::stringstream oss; // FIX ME turn into utility func? std::string name(""); mol.getPropIfPresent(common_properties::_Name, name); oss << "atom '" << name << "' idx=" << idx << " AA: "; const Atom &atm = *mol.getAtomWithIdx(idx); oss << atm.getSymbol(); if (atm.getFormalCharge()) oss << (atm.getFormalCharge() > 0 ? "+" : "") << atm.getFormalCharge(); if (atm.getNumRadicalElectrons()) oss << atm.getNumRadicalElectrons(); // these neighbors should be sorted properly? size_t numNbrs = neighbour_array[idx].Atoms.size(); // CHECK_INVARIANT(numNBrs == neighbour_array[idx].Bonds.size()); std::vector nbrs; for (size_t i = 0; i < numNbrs; ++i) { const Bond *bond = mol.getBondWithIdx(neighbour_array[idx].Bonds[i]); const Atom &nbr = *mol.getAtomWithIdx(neighbour_array[idx].Atoms[i]); nbrs.push_back(NbrData(nbr.getSymbol(), bond->getBondType(), nbr.getFormalCharge(), nbr.getNumRadicalElectrons())); } std::sort(nbrs.begin(), nbrs.end(), lessTuple); for (auto &nbr : nbrs) { std::string bs = ""; switch (std::get<1>(nbr)) { case Bond::SINGLE: bs = "-"; break; case Bond::DOUBLE: bs = "="; break; case Bond::TRIPLE: bs = "#"; break; case Bond::AROMATIC: bs = "~"; break; } if (bs.size()) oss << "(" << bs << std::get<0>(nbr); else oss << "(" << "?" << (int)std::get<1>(nbr) << "?" << std::get<0>(nbr); if (std::get<2>(nbr)) oss << (std::get<2>(nbr) > 0 ? "+" : "") << std::get<2>(nbr); if (std::get<3>(nbr)) oss << std::get<3>(nbr); oss << ")"; } return oss.str(); } } // namespace StructureCheck } // namespace RDKit