00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef __RD_SLNPARSEOPS_H__
00035 #define __RD_SLNPARSEOPS_H__
00036
00037 #include <vector>
00038 #include <GraphMol/SLNParse/SLNParse.h>
00039 #include <GraphMol/SLNParse/SLNAttribs.h>
00040 #include <GraphMol/RDKitBase.h>
00041 #include <GraphMol/RDKitQueries.h>
00042 #include <boost/lexical_cast.hpp>
00043
00044 namespace RDKit{
00045 namespace SLNParse{
00046 namespace {
00047
00048 void bookmarkAtomID(RWMol *mp,Atom *atom){
00049 PRECONDITION(mp,"bad molecule");
00050 PRECONDITION(atom,"bad atom");
00051 if(atom->hasProp("_AtomID")){
00052 unsigned int label;
00053 atom->getProp("_AtomID",label);
00054 if(mp->hasAtomBookmark(label)){
00055 std::stringstream err;
00056 err << "SLN Parser error: Atom ID " << label << " used a second time.";
00057 throw SLNParseException(err.str());
00058 }
00059 if(mp->hasBondBookmark(label)){
00060 std::stringstream err;
00061 err << "SLN Parser error: Atom ID " << label << " appears *after* its ring closure.";
00062 throw SLNParseException(err.str());
00063 }
00064 mp->setAtomBookmark(atom,label);
00065 }
00066 }
00067
00068
00069 template<typename BondType>
00070 void addBondToMol(RWMol *mp,BondType *bond){
00071 PRECONDITION(mp,"null molecule");
00072 PRECONDITION(bond,"null bond");
00073 mp->addBond(bond,true);
00074 if(bond->getBondType()==Bond::AROMATIC){
00075
00076
00077 bond->setIsAromatic(true);
00078 bond->getBeginAtom()->setIsAromatic(true);
00079 bond->getEndAtom()->setIsAromatic(true);
00080 }
00081 }
00082 }
00083
00084
00085
00086 template <typename AtomType>
00087 int startMol(std::vector<RWMol *> &molList,AtomType *firstAtom){
00088 PRECONDITION(firstAtom,"empty atom");
00089 RWMol *mp = new RWMol();
00090 mp->addAtom(firstAtom,true,true);
00091 bookmarkAtomID(mp,firstAtom);
00092
00093
00094
00095 for(unsigned int i=0;i<firstAtom->getNumExplicitHs();++i){
00096 int hIdx=mp->addAtom(new Atom(1),false,true);
00097 mp->addBond(0,hIdx,Bond::SINGLE);
00098 }
00099 firstAtom->setNumExplicitHs(0);
00100
00101
00102 int sz = molList.size();
00103 molList.push_back(mp);
00104 return sz;
00105 };
00106
00107
00108
00109 template<typename AtomType,typename BondType>
00110 void addAtomToMol(std::vector<RWMol *> &molList,unsigned int idx,AtomType *atom,
00111 BondType *bond){
00112 PRECONDITION(idx<molList.size(),"bad index");
00113 RWMol *mp=molList[idx];
00114 PRECONDITION(mp,"null molecule");
00115 PRECONDITION(atom,"empty atom");
00116 PRECONDITION(bond,"null bond");
00117
00118 Atom *a1 = mp->getActiveAtom();
00119 int atomIdx1=a1->getIdx();
00120 int atomIdx2=mp->addAtom(atom,true,true);
00121 bookmarkAtomID(mp,atom);
00122 bond->setOwningMol(mp);
00123 bond->setBeginAtomIdx(atomIdx1);
00124 bond->setEndAtomIdx(atomIdx2);
00125 addBondToMol(mp,bond);
00126
00127
00128
00129 for(unsigned int i=0;i<atom->getNumExplicitHs();++i){
00130 int hIdx=mp->addAtom(new Atom(1),false,true);
00131 mp->addBond(atomIdx2,hIdx,Bond::SINGLE);
00132 }
00133 atom->setNumExplicitHs(0);
00134
00135 }
00136
00137 template<typename AtomType>
00138 void addAtomToMol(std::vector<RWMol *> &molList,unsigned int idx,AtomType *atom){
00139 addAtomToMol(molList,idx,atom,new Bond(Bond::SINGLE));
00140 }
00141
00142
00143
00144
00145
00146
00147 template <typename BondType>
00148 void closeRingBond(std::vector<RWMol *> &molList,unsigned int molIdx,
00149 unsigned int ringIdx,BondType *bond,
00150 bool postponeAllowed=true){
00151 PRECONDITION(molIdx<molList.size(),"bad index");
00152 RWMol *mp=molList[molIdx];
00153 PRECONDITION(mp,"null molecule");
00154 PRECONDITION(bond,"Null bond");
00155
00156 if(!mp->hasAtomBookmark(ringIdx)){
00157 if(postponeAllowed){
00158
00159 bond->setOwningMol(mp);
00160 bond->setEndAtomIdx(mp->getActiveAtom()->getIdx());
00161 mp->setBondBookmark(bond,ringIdx);
00162 return;
00163 } else {
00164 std::stringstream err;
00165 err << "SLN Parser error: Ring closure " << ringIdx << " does not have a corresponding opener.";
00166 throw SLNParseException(err.str());
00167 }
00168 }
00169 Atom *opener=mp->getAtomWithBookmark(ringIdx);
00170 CHECK_INVARIANT(opener,"invalid atom");
00171
00172 Atom *closer=mp->getActiveAtom();
00173 bond->setOwningMol(mp);
00174 bond->setBeginAtom(opener);
00175 bond->setEndAtom(closer);
00176 addBondToMol(mp,bond);
00177 };
00178
00179 void closeRingBond(std::vector<RWMol *> &molList,unsigned int molIdx,unsigned int ringIdx){
00180 closeRingBond(molList,molIdx,ringIdx,new Bond(Bond::SINGLE));
00181 };
00182
00183
00184
00185 template <typename BondType>
00186 int addBranchToMol(std::vector<RWMol *> &molList,unsigned int molIdx,
00187 unsigned int branchIdx,BondType *&bond){
00188 PRECONDITION(molIdx<molList.size(),"bad index");
00189 RWMol *mp=molList[molIdx];
00190 PRECONDITION(mp,"null molecule");
00191 PRECONDITION(branchIdx<molList.size(),"bad index");
00192 RWMol *branch=molList[branchIdx];
00193 PRECONDITION(branch,"null branch");
00194 PRECONDITION(bond,"null bond");
00195
00196 unsigned int activeAtomIdx=mp->getActiveAtom()->getIdx();
00197 unsigned int nOrigAtoms=mp->getNumAtoms();
00198
00199
00200
00201
00202 mp->insertMol(*branch);
00203
00204
00205 for(ROMol::ATOM_BOOKMARK_MAP::const_iterator bmIt=branch->getAtomBookmarks()->begin();
00206 bmIt != branch->getAtomBookmarks()->end();++bmIt){
00207 if(bmIt->first<0) continue;
00208 if(mp->hasAtomBookmark(bmIt->first)){
00209 std::stringstream err;
00210 err << "SLN Parser error: Atom ID " << bmIt->first << " used a second time.";
00211 throw SLNParseException(err.str());
00212 } else if(mp->hasBondBookmark(bmIt->first)){
00213 std::stringstream err;
00214 err << "SLN Parser error: Atom ID " << bmIt->first << " appears *after* its ring closure.";
00215 throw SLNParseException(err.str());
00216 }
00217 else {
00218 CHECK_INVARIANT(bmIt->second.size()==1,"bad atom bookmark list on branch");
00219 Atom *tgtAtom=mp->getAtomWithIdx((*bmIt->second.begin())->getIdx()+nOrigAtoms);
00220 mp->setAtomBookmark(tgtAtom,bmIt->first);
00221 }
00222 }
00223
00224
00225 for(ROMol::BOND_BOOKMARK_MAP::const_iterator bmIt=branch->getBondBookmarks()->begin();
00226 bmIt != branch->getBondBookmarks()->end();++bmIt){
00227 CHECK_INVARIANT(bmIt->second.size()>=1,"bad bond bookmark list on branch");
00228 for(ROMol::BOND_PTR_LIST::const_iterator bondIt=bmIt->second.begin();
00229 bondIt!=bmIt->second.end();++bondIt){
00230 Bond *tgtBond=*bondIt;
00231 if(bmIt->first>0 && mp->hasAtomBookmark(bmIt->first)){
00232 Atom *tmpAtom=mp->getActiveAtom();
00233 mp->setActiveAtom(mp->getAtomWithIdx(tgtBond->getEndAtomIdx()+nOrigAtoms));
00234 closeRingBond(molList,molIdx,bmIt->first,tgtBond,false);
00235 mp->setActiveAtom(tmpAtom);
00236 } else {
00237
00238 tgtBond->setOwningMol(mp);
00239 tgtBond->setEndAtomIdx(tgtBond->getEndAtomIdx()+nOrigAtoms);
00240 mp->setBondBookmark(tgtBond,bmIt->first);
00241 }
00242 }
00243 }
00244
00245
00246 if(bond->getBondType()!=Bond::IONIC){
00247 bond->setOwningMol(mp);
00248 bond->setBeginAtomIdx(activeAtomIdx);
00249 bond->setEndAtomIdx(nOrigAtoms);
00250 addBondToMol(mp,bond);
00251 } else {
00252 delete bond;
00253 }
00254 bond=0;
00255
00256 delete branch;
00257 unsigned int sz = molList.size();
00258 if ( sz==branchIdx+1) {
00259 molList.resize( sz-1 );
00260 }
00261 return molIdx;
00262 };
00263
00264 int addBranchToMol(std::vector<RWMol *> &molList,unsigned int molIdx,unsigned int branchIdx){
00265 Bond *newBond=new Bond(Bond::SINGLE);
00266 return addBranchToMol(molList,molIdx,branchIdx,newBond);
00267 };
00268
00269
00270
00271 int addFragToMol(std::vector<RWMol *> &molList,unsigned int molIdx,unsigned int fragIdx){
00272 Bond *newBond=new Bond(Bond::IONIC);
00273 return addBranchToMol(molList,molIdx,fragIdx,newBond);
00274 }
00275
00276
00277 template <typename T>
00278 std::string convertToString(T val){
00279 std::string res=boost::lexical_cast<std::string>(val);
00280 return res;
00281 }
00282
00283 void CleanupAfterParseError(RWMol *mol){
00284 PRECONDITION(mol,"no molecule");
00285
00286 RWMol::BOND_BOOKMARK_MAP *marks = mol->getBondBookmarks();
00287 RWMol::BOND_BOOKMARK_MAP::iterator markI=marks->begin();
00288 while(markI != marks->end()){
00289 RWMol::BOND_PTR_LIST &bonds=markI->second;
00290 for(RWMol::BOND_PTR_LIST::iterator bondIt=bonds.begin();
00291 bondIt!=bonds.end();++bondIt){
00292 delete *bondIt;
00293 }
00294 ++markI;
00295 }
00296 }
00297 }
00298 }
00299 #endif