Files
rdkit/Code/GraphMol/Renumber.cpp
tadhurst-cdd ab5483dc51 Fix canonicalization of stereogroups (#7041)
* atropisomer handling added

* fixed non-used variables,  linking directives

* BOOST LIB start/stop fixes, linking fix

* Fixes for RDKIT CI errors

* minimalLib fix

* changed vector<enum> for java builds

* check for extra chars in CIP labeling

* removed wrong deprecated message

* fix ostrstream output error?

* restored _ChiralAtomRank to lowercase first letter

* changes for merged master

* Fixed catch label for new Catch package

* update expected psql results

* get swig wrappers building

* restore MolFileStereochem to FileParsers

* fix java wrapper for reapplyMolBlockWedging

* test changes

* some suggestions

* move a couple functions out of Bond

* Merge branch 'master' into pr/atropisomers2

* merged master

* Renamed setStereoanyFromSquiggleBond

* atropisomers in cdxml, rationalize atrop wedging, stereoGroups in drawMol

* Merge branch 'master' into pr/specialQueries

* changes from previous PR

* Iclude false chiral

* rigorous enhnced stereo canoncalization

* Added more tests and clenup

* removed commented out code

* corrected init of SmilesWriteParams

* added MolFileStereoChem.h to the header files

* Renamed Rxn parser to MrvBlockToChemicalReaction

* To make catch2 work, and match the checksum

* Fixed Structchecker errors

* fix CI for DetermineBonds catch test

* error in catch_test for CI

* Allow custom  smileWriteParams  in GetMolLayers

* misnamed entry point

* ReactionFromMrvString change name

* remove adding writeParams to GetMolLayers

* make rigorous enhanced stereo the default, and fix tests

* only one abs group no longer needs Rigorous Enhanced treatment

* changed string_view to string in catch test

* Canonicalize Enhnaced Stereo only resturne unique smiles

* Now allows or and and groups together

* internal routines inside detail scope

* fix test error

* changed string back to string_view and fixed a CHECK

* Fixes for PR review tests

* Fix RDKit_Book.rst failure on build test

* fix xqm sql test

* updated expected files for cxsmiles_test

* Fixed removal of atom attrs

* Fixed tests after merge of master

* More efficient version of Stereo Groups Canonicalization

* Fixes for ctests

* removed debug code

* readded cipLabel test

* fix generalizedSubstruct/catch_tests.cpp error

* hueristics to improve speed

* Rationaized control of abs groups

* removed unused routine

* added rigorous stereo group treatment to test

* some suggested changes

* Changes per PR review and removed some changes to smiles

* Fixed CI errors

* changes per PR review

* more PR review vhanges and cleanup

* Fixed PSql PKL change

* changes as per PR review

* Restored error type for bad mols for canonicalizeStereoGroups and added a test

* Merge master and fix test in MolDraw2D

* Fix for randomize test error and other PR review comments

* Removed unsued variable to fix mac CI

* do not force aromatization in canonicalizeStereoGroups

* changes as per PR review

---------

Co-authored-by: greg landrum <greg.landrum@gmail.com>
2024-10-25 05:09:30 +02:00

135 lines
4.2 KiB
C++

//
// Copyright (C) 2013 Greg Landrum
//
// @@ 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 <GraphMol/GraphMol.h>
#include <GraphMol/MolOps.h>
#include <RDGeneral/Exceptions.h>
#include <GraphMol/AtomIterators.h>
#include <GraphMol/BondIterators.h>
namespace RDKit {
namespace MolOps {
ROMol *renumberAtoms(const ROMol &mol,
const std::vector<unsigned int> &newOrder) {
unsigned int nAts = mol.getNumAtoms();
PRECONDITION(newOrder.size() == nAts, "bad newOrder size");
std::vector<unsigned int> revOrder(nAts);
for (unsigned int nIdx = 0; nIdx < nAts; ++nIdx) {
unsigned int oIdx = newOrder[nIdx];
if (oIdx > nAts) {
throw ValueErrorException("idx value exceeds numAtoms");
}
revOrder[oIdx] = nIdx;
}
// ------
// newOrder[i] : which atom should be in position i of the new mol
// revOrder[i] : where atom i of the original mol landed in the new mol
auto *res = new RWMol();
// copy over the atoms:
for (unsigned int nIdx = 0; nIdx < nAts; ++nIdx) {
unsigned int oIdx = newOrder[nIdx];
const Atom *oAtom = mol.getAtomWithIdx(oIdx);
Atom *nAtom = oAtom->copy();
res->addAtom(nAtom, false, true);
// take care of atom-numbering-dependent properties:
INT_VECT nAtoms;
if (nAtom->getPropIfPresent(common_properties::_ringStereoAtoms, nAtoms)) {
// FIX: ought to be able to avoid this copy.
for (auto &val : nAtoms) {
if (val < 0) {
val = -1 * (revOrder[(-val - 1)] + 1);
} else {
val = revOrder[val - 1] + 1;
}
}
nAtom->setProp(common_properties::_ringStereoAtoms, nAtoms, true);
}
unsigned int otherAtom;
if (nAtom->getPropIfPresent(common_properties::_ringStereoOtherAtom,
otherAtom)) {
otherAtom = revOrder[otherAtom];
nAtom->setProp(common_properties::_ringStereoOtherAtom, otherAtom, true);
}
}
// now the bonds:
for (ROMol::ConstBondIterator bi = mol.beginBonds(); bi != mol.endBonds();
++bi) {
const Bond *oBond = (*bi);
Bond *nBond = oBond->copy();
nBond->setBeginAtomIdx(revOrder[oBond->getBeginAtomIdx()]);
nBond->setEndAtomIdx(revOrder[oBond->getEndAtomIdx()]);
res->addBond(nBond, true);
// take care of atom-numbering-dependent properties:
for (auto &idx : nBond->getStereoAtoms()) {
idx = revOrder[idx];
}
}
// Conformers:
for (auto oConf = mol.beginConformers(); oConf != mol.endConformers();
++oConf) {
auto *nConf = new Conformer(nAts);
for (unsigned int i = 0; i < nAts; ++i) {
nConf->setAtomPos(i, (*oConf)->getAtomPos(newOrder[i]));
}
nConf->setId((*oConf)->getId());
nConf->set3D((*oConf)->is3D());
res->addConformer(nConf);
}
// update the ring info:
const RingInfo *oRings = mol.getRingInfo();
if (oRings && oRings->isInitialized()) {
RingInfo *nRings = res->getRingInfo();
nRings->reset();
nRings->initialize();
for (unsigned int i = 0; i < oRings->numRings(); ++i) {
const INT_VECT &oRing = oRings->atomRings()[i];
INT_VECT nRing(oRing.size());
for (unsigned int j = 0; j < oRing.size(); ++j) {
nRing[j] = revOrder[oRing[j]];
}
nRings->addRing(nRing, oRings->bondRings()[i]);
}
}
if (mol.getStereoGroups().size()) {
std::vector<StereoGroup> nsgs;
nsgs.reserve(mol.getStereoGroups().size());
for (const auto &osg : mol.getStereoGroups()) {
std::vector<Atom *> ats;
std::vector<Bond *> bds;
ats.reserve(osg.getAtoms().size());
bds.reserve(osg.getBonds().size());
for (const auto aptr : osg.getAtoms()) {
ats.push_back(res->getAtomWithIdx(revOrder[aptr->getIdx()]));
}
for (const auto bptr : osg.getBonds()) {
bds.push_back(
res->getBondWithIdx(bptr->getIdx())); // bonds do not change order
}
nsgs.emplace_back(osg.getGroupType(), ats, bds, osg.getReadId());
}
res->setStereoGroups(std::move(nsgs));
}
return dynamic_cast<ROMol *>(res);
} // namespace
}; // end of namespace MolOps
}; // end of namespace RDKit