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