Files
rdkit/Code/GraphMol/Renumber.cpp
Brian Kelley 95a92282d1 Dictionary access is saniztized and optimized.
o rdkit gains a RDKit::common_properties namespace that contains common string value properties

 o Dict.h and below gain getPropIfPresent that attempts to retrieve a property and returns
  true/false on success or failure.  This is used to optimize access.

 o rdkit learns how to pass property keys by reference, not value.

A new namespace has been added to RDKit, common_properties
that contains the std::string values for commonly used
properties.  This helps to avoid typos in string values
but also avoids a creation of std::strings from character
values.  All accessors (has/get/clear and getPropIfPresent) now pass
the key by reference.

Additionally, getPropIfPresent removes the double lookup
of hasProp/getProp which can be a significant speedup
in the smiles and smarts parsers (10-20%)
2015-01-15 12:23:29 -05:00

106 lines
3.4 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 <RDBoost/Exceptions.h>
#include <GraphMol/AtomIterators.h>
#include <GraphMol/BondIterators.h>
#include <boost/foreach.hpp>
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
RWMol *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.
BOOST_FOREACH(int &val,nAtoms){
if(val<0){
val=-1*(revOrder[(-val-1)]+1);
} else {
val=revOrder[val-1]+1;
}
}
nAtom->setProp(common_properties::_ringStereoAtoms,nAtoms,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:
BOOST_FOREACH(int &idx,nBond->getStereoAtoms()){
idx=revOrder[idx];
}
}
// Conformers:
for(ROMol::ConstConformerIterator oConf=mol.beginConformers();
oConf!=mol.endConformers();
++oConf){
Conformer *nConf=new Conformer(nAts);
for(unsigned int i=0;i<nAts;++i){
nConf->setAtomPos(i,(*oConf)->getAtomPos(revOrder[i]));
}
res->addConformer(nConf);
}
// update the ring info:
const RingInfo *oRings=mol.getRingInfo();
if(oRings){
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]);
}
}
return dynamic_cast<ROMol *>(res);
}
}; // end of namespace MolOps
}; // end of namespace RDKit