1 // 2 // Copyright (C) 2003-2018 Greg Landrum and Rational Discovery LLC 3 // 4 // @@ All Rights Reserved @@ 5 // This file is part of the RDKit. 6 // The contents are covered by the terms of the BSD license 7 // which is included in the file license.txt, found at the root 8 // of the RDKit source tree. 9 // 10 /*! \file ROMol.h 11 12 \brief Defines the primary molecule class \c ROMol as well as associated 13 typedefs 14 15 */ 16 17 #include <RDGeneral/export.h> 18 #ifndef RD_ROMOL_H 19 #define RD_ROMOL_H 20 21 /// Std stuff 22 #include <utility> 23 #include <map> 24 25 // boost stuff 26 #include <RDGeneral/BoostStartInclude.h> 27 #include <boost/graph/adjacency_list.hpp> 28 #include <boost/smart_ptr.hpp> 29 #include <boost/dynamic_bitset.hpp> 30 #include <RDGeneral/BoostEndInclude.h> 31 32 // our stuff 33 #include <RDGeneral/types.h> 34 #include <RDGeneral/RDProps.h> 35 #include "Atom.h" 36 #include "Bond.h" 37 #include "Conformer.h" 38 #include "SubstanceGroup.h" 39 #include "StereoGroup.h" 40 41 namespace RDKit { 42 class SubstanceGroup; 43 class Atom; 44 class Bond; 45 //! This is the BGL type used to store the topology: 46 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, 47 Atom *, Bond *> 48 MolGraph; 49 class MolPickler; 50 class RWMol; 51 class QueryAtom; 52 class QueryBond; 53 class RingInfo; 54 55 template <class T1, class T2> 56 class AtomIterator_; 57 class BondIterator_; 58 class ConstBondIterator_; 59 60 template <class T1, class T2> 61 class AromaticAtomIterator_; 62 template <class T1, class T2> 63 class HeteroatomIterator_; 64 template <class T1, class T2> 65 class QueryAtomIterator_; 66 template <class T1, class T2> 67 class MatchingAtomIterator_; 68 69 RDKIT_GRAPHMOL_EXPORT extern const int ci_RIGHTMOST_ATOM; 70 RDKIT_GRAPHMOL_EXPORT extern const int ci_LEADING_BOND; 71 RDKIT_GRAPHMOL_EXPORT extern const int ci_ATOM_HOLDER; 72 73 //! ROMol is a molecule class that is intended to have a fixed topology 74 /*! 75 This is the primary class for most molecule operations. 76 77 If you need to be manipulating the molecule (e.g. adding or deleting 78 atoms or bonds, use an RWMol instead. 79 80 <b>Notes:</b> 81 - each ROMol maintains a Dict of \c properties: 82 - Each \c property is keyed by name and can store an 83 arbitrary type. 84 - \c Properties can be marked as \c calculated, in which case 85 they will be cleared when the \c clearComputedProps() method 86 is called. 87 - Because they have no impact upon chemistry, all \c property 88 operations are \c const, this allows extra flexibility for 89 clients who need to store extra data on ROMol objects. 90 91 - each ROMol has collections of \c bookmarks for Atoms and Bonds: 92 - the Atom bookmarks and Bond bookmarks are stored separately 93 from each other 94 - each \c bookmark, an integer, can map to more than one 95 Atom or Bond 96 - these are currently used in molecule construction, but 97 could also be useful for reaction mapping and the like 98 99 - information about rings (SSSR and the like) is stored in the 100 molecule's RingInfo pointer. 101 102 */ 103 104 //! \name C++11 Iterators 105 106 template <class Graph, class Vertex> 107 struct CXXAtomIterator { 108 Graph *graph; 109 typename Graph::vertex_iterator vstart, vend; 110 111 struct CXXAtomIter { 112 Graph *graph; 113 typename Graph::vertex_iterator pos; 114 Atom *current; 115 CXXAtomIterCXXAtomIterator::CXXAtomIter116 CXXAtomIter(Graph *graph, typename Graph::vertex_iterator pos) 117 : graph(graph), pos(pos), current(nullptr) {} 118 119 Vertex &operator*() { 120 current = (*graph)[*pos]; 121 return current; 122 } 123 CXXAtomIter &operator++() { 124 ++pos; 125 return *this; 126 } 127 bool operator!=(const CXXAtomIter &it) const { return pos != it.pos; } 128 }; 129 CXXAtomIteratorCXXAtomIterator130 CXXAtomIterator(Graph *graph) : graph(graph) { 131 auto vs = boost::vertices(*graph); 132 vstart = vs.first; 133 vend = vs.second; 134 } beginCXXAtomIterator135 CXXAtomIter begin() { return {graph, vstart}; } endCXXAtomIterator136 CXXAtomIter end() { return {graph, vend}; } 137 }; 138 139 template <class Graph, class Edge> 140 struct CXXBondIterator { 141 Graph *graph; 142 typename Graph::edge_iterator vstart, vend; 143 144 struct CXXBondIter { 145 Graph *graph; 146 typename Graph::edge_iterator pos; 147 Bond *current; 148 CXXBondIterCXXBondIterator::CXXBondIter149 CXXBondIter(Graph *graph, typename Graph::edge_iterator pos) 150 : graph(graph), pos(pos), current(nullptr) {} 151 152 Edge &operator*() { 153 current = (*graph)[*pos]; 154 return current; 155 } 156 CXXBondIter &operator++() { 157 ++pos; 158 return *this; 159 } 160 bool operator!=(const CXXBondIter &it) const { return pos != it.pos; } 161 }; 162 CXXBondIteratorCXXBondIterator163 CXXBondIterator(Graph *graph) : graph(graph) { 164 auto vs = boost::edges(*graph); 165 vstart = vs.first; 166 vend = vs.second; 167 } beginCXXBondIterator168 CXXBondIter begin() { return {graph, vstart}; } endCXXBondIterator169 CXXBondIter end() { return {graph, vend}; } 170 }; 171 172 class RDKIT_GRAPHMOL_EXPORT ROMol : public RDProps { 173 public: 174 friend class MolPickler; 175 friend class RWMol; 176 177 //! \cond TYPEDEFS 178 179 //! \name typedefs 180 //@{ 181 typedef MolGraph::vertex_descriptor vertex_descriptor; 182 typedef MolGraph::edge_descriptor edge_descriptor; 183 184 typedef MolGraph::edge_iterator EDGE_ITER; 185 typedef MolGraph::out_edge_iterator OEDGE_ITER; 186 typedef MolGraph::vertex_iterator VERTEX_ITER; 187 typedef MolGraph::adjacency_iterator ADJ_ITER; 188 typedef std::pair<EDGE_ITER, EDGE_ITER> BOND_ITER_PAIR; 189 typedef std::pair<OEDGE_ITER, OEDGE_ITER> OBOND_ITER_PAIR; 190 typedef std::pair<VERTEX_ITER, VERTEX_ITER> ATOM_ITER_PAIR; 191 typedef std::pair<ADJ_ITER, ADJ_ITER> ADJ_ITER_PAIR; 192 193 typedef std::vector<Atom *> ATOM_PTR_VECT; 194 typedef ATOM_PTR_VECT::iterator ATOM_PTR_VECT_I; 195 typedef ATOM_PTR_VECT::const_iterator ATOM_PTR_VECT_CI; 196 typedef std::vector<Bond *> BOND_PTR_VECT; 197 typedef BOND_PTR_VECT::iterator BOND_PTR_VECT_I; 198 typedef BOND_PTR_VECT::const_iterator BOND_PTR_VECT_CI; 199 200 typedef std::list<Atom *> ATOM_PTR_LIST; 201 typedef ATOM_PTR_LIST::iterator ATOM_PTR_LIST_I; 202 typedef ATOM_PTR_LIST::const_iterator ATOM_PTR_LIST_CI; 203 typedef std::list<Bond *> BOND_PTR_LIST; 204 typedef BOND_PTR_LIST::iterator BOND_PTR_LIST_I; 205 typedef BOND_PTR_LIST::const_iterator BOND_PTR_LIST_CI; 206 207 // list of conformations 208 typedef std::list<CONFORMER_SPTR> CONF_SPTR_LIST; 209 typedef CONF_SPTR_LIST::iterator CONF_SPTR_LIST_I; 210 typedef CONF_SPTR_LIST::const_iterator CONF_SPTR_LIST_CI; 211 typedef std::pair<CONF_SPTR_LIST_I, CONF_SPTR_LIST_I> CONFS_I_PAIR; 212 213 // ROFIX: these will need to be readonly somehow? 214 typedef std::map<int, ATOM_PTR_LIST> ATOM_BOOKMARK_MAP; 215 typedef std::map<int, BOND_PTR_LIST> BOND_BOOKMARK_MAP; 216 217 typedef class AtomIterator_<Atom, ROMol> AtomIterator; 218 typedef class AtomIterator_<const Atom, const ROMol> ConstAtomIterator; 219 typedef class BondIterator_ BondIterator; 220 typedef class ConstBondIterator_ ConstBondIterator; 221 typedef class AromaticAtomIterator_<Atom, ROMol> AromaticAtomIterator; 222 typedef class AromaticAtomIterator_<const Atom, const ROMol> 223 ConstAromaticAtomIterator; 224 typedef class HeteroatomIterator_<Atom, ROMol> HeteroatomIterator; 225 typedef class HeteroatomIterator_<const Atom, const ROMol> 226 ConstHeteroatomIterator; 227 typedef class QueryAtomIterator_<Atom, ROMol> QueryAtomIterator; 228 typedef class QueryAtomIterator_<const Atom, const ROMol> 229 ConstQueryAtomIterator; 230 typedef class MatchingAtomIterator_<Atom, ROMol> MatchingAtomIterator; 231 typedef class MatchingAtomIterator_<const Atom, const ROMol> 232 ConstMatchingAtomIterator; 233 234 typedef CONF_SPTR_LIST_I ConformerIterator; 235 typedef CONF_SPTR_LIST_CI ConstConformerIterator; 236 237 //@} 238 //! \endcond 239 240 //! C++11 Range iterator 241 /*! 242 <b>Usage</b> 243 \code 244 for(auto atom : mol.atoms()) { 245 atom->getIdx(); 246 }; 247 \endcode 248 */ 249 atoms()250 CXXAtomIterator<MolGraph, Atom *> atoms() { return {&d_graph}; } 251 atoms()252 CXXAtomIterator<const MolGraph, Atom *const> atoms() const { 253 return {&d_graph}; 254 } 255 256 /*! 257 <b>Usage</b> 258 \code 259 for(auto bond : mol.bonds()) { 260 bond->getIdx(); 261 }; 262 \endcode 263 */ 264 bonds()265 CXXBondIterator<MolGraph, Bond *> bonds() { return {&d_graph}; } 266 bonds()267 CXXBondIterator<const MolGraph, Bond *const> bonds() const { 268 return {&d_graph}; 269 } 270 ROMol()271 ROMol() : RDProps() { initMol(); } 272 273 //! copy constructor with a twist 274 /*! 275 \param other the molecule to be copied 276 \param quickCopy (optional) if this is true, the resulting ROMol will not 277 copy any of the properties or bookmarks and conformers from \c other. 278 This can 279 make the copy substantially faster (thus the name). 280 \param confId (optional) if this is >=0, the resulting ROMol will contain 281 only 282 the specified conformer from \c other. 283 */ 284 ROMol(const ROMol &other, bool quickCopy = false, int confId = -1) RDProps()285 : RDProps() { 286 dp_ringInfo = nullptr; 287 initFromOther(other, quickCopy, confId); 288 numBonds = rdcast<unsigned int>(boost::num_edges(d_graph)); 289 }; 290 //! construct a molecule from a pickle string 291 ROMol(const std::string &binStr); 292 ~ROMol()293 virtual ~ROMol() { destroy(); }; 294 295 //@} 296 //! \name Atoms 297 //@{ 298 299 //! returns our number of atoms getNumAtoms()300 inline unsigned int getNumAtoms() const { 301 return rdcast<unsigned int>(boost::num_vertices(d_graph)); 302 }; 303 unsigned int getNumAtoms(bool onlyExplicit) const; 304 //! returns our number of heavy atoms (atomic number > 1) 305 unsigned int getNumHeavyAtoms() const; 306 //! returns a pointer to a particular Atom 307 Atom *getAtomWithIdx(unsigned int idx); 308 //! \overload 309 const Atom *getAtomWithIdx(unsigned int idx) const; 310 //! \overload 311 template <class U> getAtomWithIdx(const U idx)312 Atom *getAtomWithIdx(const U idx) { 313 return getAtomWithIdx(rdcast<unsigned int>(idx)); 314 } 315 //! \overload 316 template <class U> getAtomWithIdx(const U idx)317 const Atom *getAtomWithIdx(const U idx) const { 318 return getAtomWithIdx(rdcast<unsigned int>(idx)); 319 } 320 //! returns the degree (number of neighbors) of an Atom in the graph 321 unsigned int getAtomDegree(const Atom *at) const; 322 //@} 323 324 //! \name Bonds 325 //@{ 326 327 //! returns our number of Bonds 328 unsigned int getNumBonds(bool onlyHeavy = 1) const; 329 //! returns a pointer to a particular Bond 330 Bond *getBondWithIdx(unsigned int idx); 331 //! \overload 332 const Bond *getBondWithIdx(unsigned int idx) const; 333 //! \overload 334 template <class U> getBondWithIdx(const U idx)335 Bond *getBondWithIdx(const U idx) { 336 return getBondWithIdx(rdcast<unsigned int>(idx)); 337 } 338 //! \overload 339 template <class U> getBondWithIdx(const U idx)340 const Bond *getBondWithIdx(const U idx) const { 341 return getBondWithIdx(rdcast<unsigned int>(idx)); 342 } 343 //! returns a pointer to the bond between two atoms, Null on failure 344 Bond *getBondBetweenAtoms(unsigned int idx1, unsigned int idx2); 345 //! \overload 346 const Bond *getBondBetweenAtoms(unsigned int idx1, unsigned int idx2) const; 347 //! \overload 348 template <class U, class V> getBondBetweenAtoms(const U idx1,const V idx2)349 Bond *getBondBetweenAtoms(const U idx1, const V idx2) { 350 return getBondBetweenAtoms(rdcast<unsigned int>(idx1), 351 rdcast<unsigned int>(idx2)); 352 } 353 //! \overload 354 template <class U, class V> getBondBetweenAtoms(const U idx1,const V idx2)355 const Bond *getBondBetweenAtoms(const U idx1, const V idx2) const { 356 return getBondBetweenAtoms(rdcast<unsigned int>(idx1), 357 rdcast<unsigned int>(idx2)); 358 } 359 360 //@} 361 362 //! \name Bookmarks 363 //@{ 364 365 //! associates an Atom pointer with a bookmark setAtomBookmark(Atom * at,int mark)366 void setAtomBookmark(Atom *at, int mark) { 367 d_atomBookmarks[mark].push_back(at); 368 }; 369 //! associates an Atom pointer with a bookmark replaceAtomBookmark(Atom * at,int mark)370 void replaceAtomBookmark(Atom *at, int mark) { 371 d_atomBookmarks[mark].clear(); 372 d_atomBookmarks[mark].push_back(at); 373 }; 374 //! returns the first Atom associated with the \c bookmark provided 375 Atom *getAtomWithBookmark(int mark); 376 //! returns the Atom associated with the \c bookmark provided 377 //! a check is made to ensure it is the only atom with that bookmark 378 Atom *getUniqueAtomWithBookmark(int mark); 379 //! returns all Atoms associated with the \c bookmark provided 380 ATOM_PTR_LIST &getAllAtomsWithBookmark(int mark); 381 //! removes a \c bookmark from our collection 382 void clearAtomBookmark(int mark); 383 //! removes a particular Atom from the list associated with the \c bookmark 384 void clearAtomBookmark(int mark, const Atom *atom); 385 386 //! blows out all atomic \c bookmarks clearAllAtomBookmarks()387 void clearAllAtomBookmarks() { d_atomBookmarks.clear(); }; 388 //! queries whether or not any atoms are associated with a \c bookmark hasAtomBookmark(int mark)389 bool hasAtomBookmark(int mark) const { return d_atomBookmarks.count(mark); }; 390 //! returns a pointer to all of our atom \c bookmarks getAtomBookmarks()391 ATOM_BOOKMARK_MAP *getAtomBookmarks() { return &d_atomBookmarks; }; 392 393 //! associates a Bond pointer with a bookmark setBondBookmark(Bond * bond,int mark)394 void setBondBookmark(Bond *bond, int mark) { 395 d_bondBookmarks[mark].push_back(bond); 396 }; 397 //! returns the first Bond associated with the \c bookmark provided 398 Bond *getBondWithBookmark(int mark); 399 //! returns the Bond associated with the \c bookmark provided 400 //! a check is made to ensure it is the only bond with that bookmark 401 Bond *getUniqueBondWithBookmark(int mark); 402 //! returns all bonds associated with the \c bookmark provided 403 BOND_PTR_LIST &getAllBondsWithBookmark(int mark); 404 //! removes a \c bookmark from our collection 405 void clearBondBookmark(int mark); 406 //! removes a particular Bond from the list associated with the \c bookmark 407 void clearBondBookmark(int mark, const Bond *bond); 408 409 //! blows out all bond \c bookmarks clearAllBondBookmarks()410 void clearAllBondBookmarks() { d_bondBookmarks.clear(); }; 411 //! queries whether or not any bonds are associated with a \c bookmark hasBondBookmark(int mark)412 bool hasBondBookmark(int mark) const { return d_bondBookmarks.count(mark); }; 413 //! returns a pointer to all of our bond \c bookmarks getBondBookmarks()414 BOND_BOOKMARK_MAP *getBondBookmarks() { return &d_bondBookmarks; }; 415 416 //@} 417 418 //! \name Conformers 419 //@{ 420 421 //! return the conformer with a specified ID 422 //! if the ID is negative the first conformation will be returned 423 const Conformer &getConformer(int id = -1) const; 424 425 //! return the conformer with a specified ID 426 //! if the ID is negative the first conformation will be returned 427 Conformer &getConformer(int id = -1); 428 429 //! Delete the conformation with the specified ID 430 void removeConformer(unsigned int id); 431 432 //! Clear all the conformations on the molecule clearConformers()433 void clearConformers() { d_confs.clear(); } 434 435 //! Add a new conformation to the molecule 436 /*! 437 \param conf - conformation to be added to the molecule, this molecule takes 438 ownership 439 of the conformer 440 \param assignId - a unique ID will be assigned to the conformation if 441 true 442 otherwise it is assumed that the conformation already has 443 an (unique) ID set 444 */ 445 unsigned int addConformer(Conformer *conf, bool assignId = false); 446 getNumConformers()447 inline unsigned int getNumConformers() const { 448 return rdcast<unsigned int>(d_confs.size()); 449 } 450 451 //! \name Topology 452 //@{ 453 454 //! returns a pointer to our RingInfo structure 455 //! <b>Note:</b> the client should not delete this. getRingInfo()456 RingInfo *getRingInfo() const { return dp_ringInfo; }; 457 458 //! provides access to all neighbors around an Atom 459 /*! 460 \param at the atom whose neighbors we are looking for 461 462 <b>Usage</b> 463 \code 464 ... mol is a const ROMol & ... 465 ... atomPtr is a const Atom * ... 466 ... requires #include <boost/range/iterator_range.hpp> 467 for (const auto &nbri : 468 boost::make_iterator_range(m.getAtomNeighbors(atomPtr))) { 469 const auto &nbr = (*m)[nbri]; 470 // nbr is an atom pointer 471 } 472 473 \endcode 474 475 */ 476 ADJ_ITER_PAIR getAtomNeighbors(Atom const *at) const; 477 478 //! provides access to all Bond objects connected to an Atom 479 /*! 480 \param at the atom whose neighbors we are looking for 481 482 <b>Usage</b> 483 \code 484 ... mol is a const ROMol & ... 485 ... atomPtr is a const Atom * ... 486 ... requires #include <boost/range/iterator_range.hpp> 487 for (const auto &nbri : 488 boost::make_iterator_range(m.getAtomBonds(atomPtr))) { 489 const auto &nbr = (*m)[nbri]; 490 // nbr is a bond pointer 491 } 492 \endcode 493 or, if you need a non-const Bond *: 494 \code 495 ... mol is a const ROMol & ... 496 ... atomPtr is a const Atom * ... 497 ... requires #include <boost/range/iterator_range.hpp> 498 for (const auto &nbri : 499 boost::make_iterator_range(m.getAtomBonds(atomPtr))) { 500 auto nbr = (*m)[nbri]; 501 // nbr is a bond pointer 502 } 503 \endcode 504 505 506 */ 507 OBOND_ITER_PAIR getAtomBonds(Atom const *at) const; 508 509 //! returns an iterator pair for looping over all Atoms 510 /*! 511 512 <b>Usage</b> 513 \code 514 515 ROMol::VERTEX_ITER atBegin,atEnd; 516 boost::tie(atBegin,atEnd) = mol.getVertices(); 517 while(atBegin!=atEnd){ 518 ATOM_SPTR at2=mol[*atBegin]; 519 ... do something with the Atom ... 520 ++atBegin; 521 } 522 \endcode 523 */ 524 ATOM_ITER_PAIR getVertices(); 525 //! returns an iterator pair for looping over all Bonds 526 /*! 527 528 <b>Usage</b> 529 \code 530 531 ROMol::EDGE_ITER firstB,lastB; 532 boost::tie(firstB,lastB) = mol.getEdges(); 533 while(firstB!=lastB){ 534 BOND_SPTR bond = mol[*firstB]; 535 ... do something with the Bond ... 536 ++firstB; 537 } 538 \endcode 539 */ 540 BOND_ITER_PAIR getEdges(); 541 //! \overload 542 ATOM_ITER_PAIR getVertices() const; 543 //! \overload 544 BOND_ITER_PAIR getEdges() const; 545 546 //! brief returns a pointer to our underlying BGL object 547 /*! 548 This can be useful if you need to call other BGL algorithms: 549 550 Here's an example: 551 \code 552 ... mol is a const ROMol ... 553 ... mapping is an INT_VECT ... 554 mapping.resize(mol.getNumAtoms()); 555 const MolGraph &G_p = mol.getTopology(); 556 int res = boost::connected_components(G_p,&mapping[0]); 557 \endcode 558 */ getTopology()559 MolGraph const &getTopology() const { return d_graph; }; 560 //@} 561 562 //! \name Iterators 563 //@{ 564 565 //! get an AtomIterator pointing at our first Atom 566 AtomIterator beginAtoms(); 567 //! \overload 568 ConstAtomIterator beginAtoms() const; 569 //! get an AtomIterator pointing at the end of our Atoms 570 AtomIterator endAtoms(); 571 //! \overload 572 ConstAtomIterator endAtoms() const; 573 //! get a BondIterator pointing at our first Bond 574 BondIterator beginBonds(); 575 //! \overload 576 ConstBondIterator beginBonds() const; 577 //! get a BondIterator pointing at the end of our Bonds 578 BondIterator endBonds(); 579 //! \overload 580 ConstBondIterator endBonds() const; 581 582 //! get an AtomIterator pointing at our first aromatic Atom 583 AromaticAtomIterator beginAromaticAtoms(); 584 //! \overload 585 ConstAromaticAtomIterator beginAromaticAtoms() const; 586 //! get an AtomIterator pointing at the end of our Atoms 587 AromaticAtomIterator endAromaticAtoms(); 588 //! \overload 589 ConstAromaticAtomIterator endAromaticAtoms() const; 590 591 //! get an AtomIterator pointing at our first hetero Atom 592 HeteroatomIterator beginHeteros(); 593 //! \overload 594 ConstHeteroatomIterator beginHeteros() const; 595 //! get an AtomIterator pointing at the end of our Atoms 596 HeteroatomIterator endHeteros(); 597 //! \overload 598 ConstHeteroatomIterator endHeteros() const; 599 600 //! get an AtomIterator pointing at our first Atom that matches \c query 601 QueryAtomIterator beginQueryAtoms(QueryAtom const *query); 602 //! \overload 603 ConstQueryAtomIterator beginQueryAtoms(QueryAtom const *) const; 604 //! get an AtomIterator pointing at the end of our Atoms 605 QueryAtomIterator endQueryAtoms(); 606 //! \overload 607 ConstQueryAtomIterator endQueryAtoms() const; 608 609 //! get an AtomIterator pointing at our first Atom that matches \c query 610 MatchingAtomIterator beginMatchingAtoms(bool (*query)(Atom *)); 611 //! \overload 612 ConstMatchingAtomIterator beginMatchingAtoms( 613 bool (*query)(const Atom *)) const; 614 //! get an AtomIterator pointing at the end of our Atoms 615 MatchingAtomIterator endMatchingAtoms(); 616 //! \overload 617 ConstMatchingAtomIterator endMatchingAtoms() const; 618 beginConformers()619 inline ConformerIterator beginConformers() { return d_confs.begin(); } 620 endConformers()621 inline ConformerIterator endConformers() { return d_confs.end(); } 622 beginConformers()623 inline ConstConformerIterator beginConformers() const { 624 return d_confs.begin(); 625 } 626 endConformers()627 inline ConstConformerIterator endConformers() const { return d_confs.end(); } 628 629 //@} 630 631 //! \name Properties 632 //@{ 633 634 //! clears all of our \c computed \c properties 635 void clearComputedProps(bool includeRings = true) const; 636 //! calculates any of our lazy \c properties 637 /*! 638 <b>Notes:</b> 639 - this calls \c updatePropertyCache() on each of our Atoms and Bonds 640 */ 641 void updatePropertyCache(bool strict = true); 642 643 bool needsUpdatePropertyCache() const; 644 645 //@} 646 647 //! \name Misc 648 //@{ 649 //! sends some debugging info to a stream 650 void debugMol(std::ostream &str) const; 651 //@} 652 653 Atom *operator[](const vertex_descriptor &v) { return d_graph[v]; }; 654 const Atom *operator[](const vertex_descriptor &v) const { 655 return d_graph[v]; 656 }; 657 658 Bond *operator[](const edge_descriptor &e) { return d_graph[e]; }; 659 const Bond *operator[](const edge_descriptor &e) const { return d_graph[e]; }; 660 661 //! Gets a reference to the groups of atoms with relative stereochemistry 662 /*! 663 Stereo groups are also called enhanced stereochemistry in the SDF/Mol3000 664 file format. 665 */ getStereoGroups()666 const std::vector<StereoGroup> &getStereoGroups() const { 667 return d_stereo_groups; 668 } 669 670 private: 671 MolGraph d_graph; 672 ATOM_BOOKMARK_MAP d_atomBookmarks; 673 BOND_BOOKMARK_MAP d_bondBookmarks; 674 RingInfo *dp_ringInfo = nullptr; 675 CONF_SPTR_LIST d_confs; 676 std::vector<SubstanceGroup> d_sgroups; 677 std::vector<StereoGroup> d_stereo_groups; 678 std::unique_ptr<boost::dynamic_bitset<>> dp_delAtoms = nullptr; 679 std::unique_ptr<boost::dynamic_bitset<>> dp_delBonds = nullptr; 680 681 friend RDKIT_GRAPHMOL_EXPORT std::vector<SubstanceGroup> &getSubstanceGroups( 682 ROMol &); 683 friend RDKIT_GRAPHMOL_EXPORT const std::vector<SubstanceGroup> 684 &getSubstanceGroups(const ROMol &); clearSubstanceGroups()685 void clearSubstanceGroups() { d_sgroups.clear(); } 686 687 ROMol &operator=( 688 const ROMol &); // disable assignment, RWMol's support assignment 689 690 protected: 691 unsigned int numBonds{0}; 692 #ifndef WIN32 693 private: 694 #endif 695 void initMol(); 696 virtual void destroy(); 697 //! adds an Atom to our collection 698 /*! 699 \param atom pointer to the Atom to add 700 \param updateLabel (optional) if this is true, the new Atom will be 701 our \c activeAtom 702 \param takeOwnership (optional) if this is true, we take ownership of \c 703 atom 704 instead of copying it. 705 706 \return the new number of atoms 707 */ 708 unsigned int addAtom(Atom *atom, bool updateLabel = true, 709 bool takeOwnership = false); 710 //! adds a Bond to our collection 711 /*! 712 \param bond pointer to the Bond to add 713 \param takeOwnership (optional) if this is true, we take ownership of \c 714 bond 715 instead of copying it. 716 717 \return the new number of bonds 718 */ 719 unsigned int addBond(Bond *bond, bool takeOwnership = false); 720 721 //! Sets groups of atoms with relative stereochemistry 722 /*! 723 \param stereo_groups the new set of stereo groups. All will be replaced. 724 725 Stereo groups are also called enhanced stereochemistry in the SDF/Mol3000 726 file format. stereo_groups should be std::move()ed into this function. 727 */ 728 void setStereoGroups(std::vector<StereoGroup> stereo_groups); 729 //! adds a Bond to our collection 730 /*! 731 \param bond pointer to the Bond to add 732 733 \return the new number of bonds 734 735 <b>Note:</b> since this is using a smart pointer, we don't need to worry 736 about 737 issues of ownership. 738 */ 739 void initFromOther(const ROMol &other, bool quickCopy, int confId); 740 }; 741 742 typedef std::vector<ROMol> MOL_VECT; 743 typedef boost::shared_ptr<ROMol> ROMOL_SPTR; 744 typedef std::vector<ROMol *> MOL_PTR_VECT; 745 typedef std::vector<ROMOL_SPTR> MOL_SPTR_VECT; 746 747 typedef MOL_PTR_VECT::const_iterator MOL_PTR_VECT_CI; 748 typedef MOL_PTR_VECT::iterator MOL_PTR_VECT_I; 749 750 }; // namespace RDKit 751 #endif 752