mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
142 lines
4.2 KiB
C++
142 lines
4.2 KiB
C++
//
|
|
// 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 <algorithm>
|
|
#include <tuple>
|
|
|
|
namespace RDKit {
|
|
namespace StructureCheck {
|
|
|
|
void SetupNeighbourhood(const ROMol &mol,
|
|
std::vector<Neighbourhood> &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<RDGeom::Point3D> &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<std::string, int, int, int> 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<Neighbourhood> &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<NbrData> 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
|