RDKit
Open-source cheminformatics and machine learning.
Atom.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2014 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 Atom.h
11 
12  \brief Defines the Atom class and associated typedefs
13 
14 */
15 #include <RDGeneral/export.h>
16 #ifndef _RD_ATOM_H
17 #define _RD_ATOM_H
18 
19 // Std stuff
20 #include <iostream>
21 
22 // ours
23 #include <RDGeneral/Invariant.h>
24 #include <Query/QueryObjects.h>
25 #include <RDGeneral/types.h>
26 #include <RDGeneral/RDProps.h>
27 #include <GraphMol/details.h>
28 
29 namespace RDKit {
30 class ROMol;
31 class RWMol;
32 class AtomMonomerInfo;
33 
34 //! The class for representing atoms
35 /*!
36 
37  <b>Notes:</b>
38  - many of the methods of Atom require that the Atom be associated
39  with a molecule (an ROMol).
40  - each Atom maintains a Dict of \c properties:
41  - Each \c property is keyed by name and can store an
42  arbitrary type.
43  - \c Properties can be marked as \c calculated, in which case
44  they will be cleared when the \c clearComputedProps() method
45  is called.
46  - Because they have no impact upon chemistry, all \c property
47  operations are \c const, this allows extra flexibility for
48  clients who need to store extra data on Atom objects.
49  - Atom objects are lazy about computing their explicit and implicit valence
50  values. These will not be computed until their values are requested.
51 
52  <b>Chirality:</b>
53 
54  The chirality of an Atom is determined by two things:
55  - its \c chiralTag
56  - the input order of its bonds (see note below for handling of
57  implicit Hs)
58 
59  For tetrahedral coordination, the \c chiralTag tells you what
60  direction you have to rotate to get from bond 2 to bond 3 while looking
61  down bond 1. This is pretty much identical to the SMILES representation of
62  chirality.
63 
64  NOTE: if an atom has an implicit H, the bond to that H is considered to be
65  at the *end* of the list of other bonds.
66 
67 */
69  friend class MolPickler; //!< the pickler needs access to our privates
70  friend class ROMol;
71  friend class RWMol;
72 
73  public:
74  // FIX: grn...
76 
77  //! store hybridization
78  typedef enum {
79  UNSPECIFIED = 0, //!< hybridization that hasn't been specified
80  S,
81  SP,
82  SP2,
83  SP3,
86  OTHER //!< unrecognized hybridization
87  } HybridizationType;
88 
89  //! store type of chirality
90  typedef enum {
91  CHI_UNSPECIFIED = 0, //!< chirality that hasn't been specified
92  CHI_TETRAHEDRAL_CW, //!< tetrahedral: clockwise rotation (SMILES \@\@)
93  CHI_TETRAHEDRAL_CCW, //!< tetrahedral: counter-clockwise rotation (SMILES
94  //\@)
95  CHI_OTHER //!< some unrecognized type of chirality
96  } ChiralType;
97 
98  Atom();
99  //! construct an Atom with a particular atomic number
100  explicit Atom(unsigned int num);
101  //! construct an Atom with a particular symbol (looked up in the
102  /// PeriodicTable)
103  explicit Atom(const std::string &what);
104  Atom(const Atom &other);
105  Atom &operator=(const Atom &other);
106  virtual ~Atom();
107 
108  //! makes a copy of this Atom and returns a pointer to it.
109  /*!
110  <b>Note:</b> the caller is responsible for <tt>delete</tt>ing the result
111  */
112  virtual Atom *copy() const;
113 
114  //! returns our atomic number
115  int getAtomicNum() const { return d_atomicNum; }
116  //! sets our atomic number
117  void setAtomicNum(int newNum) { d_atomicNum = newNum; }
118 
119  //! returns our symbol (determined by our atomic number)
120  std::string getSymbol() const;
121 
122  //! returns whether or not this instance belongs to a molecule
123  bool hasOwningMol() const { return dp_mol != nullptr; }
124 
125  //! returns a reference to the ROMol that owns this instance
126  ROMol &getOwningMol() const {
127  PRECONDITION(dp_mol, "no owner");
128  return *dp_mol;
129  }
130 
131  //! returns our index within the ROMol
132  unsigned int getIdx() const { return d_index; }
133  //! sets our index within the ROMol
134  /*!
135  <b>Notes:</b>
136  - this makes no sense if we do not have an owning molecule
137  - the index should be <tt>< this->getOwningMol()->getNumAtoms()</tt>
138  */
139  void setIdx(unsigned int index) { d_index = index; }
140  //! overload
141  template <class U>
142  void setIdx(const U index) {
143  setIdx(rdcast<unsigned int>(index));
144  }
145  //! returns the explicit degree of the Atom (number of bonded
146  //! neighbors in the graph)
147  /*!
148  <b>Notes:</b>
149  - requires an owning molecule
150  */
151  unsigned int getDegree() const;
152 
153  //! returns the total degree of the Atom (number of bonded
154  //! neighbors + number of Hs)
155  /*!
156  <b>Notes:</b>
157  - requires an owning molecule
158  */
159  unsigned int getTotalDegree() const;
160 
161  //! \brief returns the total number of Hs (implicit and explicit) that
162  //! this Atom is bound to
163  /*!
164  <b>Notes:</b>
165  - requires an owning molecule
166  */
167  unsigned int getTotalNumHs(bool includeNeighbors = false) const;
168 
169  //! \brief returns the total valence (implicit and explicit)
170  //! for an atom
171  /*!
172  <b>Notes:</b>
173  - requires an owning molecule
174  */
175  unsigned int getTotalValence() const;
176 
177  //! returns the number of implicit Hs this Atom is bound to
178  /*!
179  <b>Notes:</b>
180  - requires an owning molecule
181  */
182  unsigned int getNumImplicitHs() const;
183 
184  //! returns the explicit valence (including Hs) of this atom
185  int getExplicitValence() const;
186 
187  //! returns the implicit valence for this Atom
188  /*!
189  <b>Notes:</b>
190  - requires an owning molecule
191  */
192  int getImplicitValence() const;
193 
194  //! returns the number of radical electrons for this Atom
195  /*!
196  <b>Notes:</b>
197  - requires an owning molecule
198  */
199  unsigned int getNumRadicalElectrons() const { return d_numRadicalElectrons; }
200  void setNumRadicalElectrons(unsigned int num) { d_numRadicalElectrons = num; }
201 
202  //! returns the formal charge of this atom
203  int getFormalCharge() const { return d_formalCharge; }
204  //! set's the formal charge of this atom
205  void setFormalCharge(int what) { d_formalCharge = what; }
206 
207  //! \brief sets our \c noImplicit flag, indicating whether or not
208  //! we are allowed to have implicit Hs
209  void setNoImplicit(bool what) { df_noImplicit = what; }
210  //! returns the \c noImplicit flag
211  bool getNoImplicit() const { return df_noImplicit; }
212 
213  //! sets our number of explicit Hs
214  void setNumExplicitHs(unsigned int what) { d_numExplicitHs = what; }
215  //! returns our number of explicit Hs
216  unsigned int getNumExplicitHs() const { return d_numExplicitHs; }
217 
218  //! sets our \c isAromatic flag, indicating whether or not we are aromatic
219  void setIsAromatic(bool what) { df_isAromatic = what; }
220  //! returns our \c isAromatic flag
221  bool getIsAromatic() const { return df_isAromatic; }
222 
223  //! returns our mass
224  double getMass() const;
225 
226  //! sets our isotope number
227  void setIsotope(unsigned int what);
228  //! returns our isotope number
229  unsigned int getIsotope() const { return d_isotope; }
230 
231  //! sets our \c chiralTag
232  void setChiralTag(ChiralType what) { d_chiralTag = what; }
233  //! inverts our \c chiralTag
235  //! returns our \c chiralTag
237  return static_cast<ChiralType>(d_chiralTag);
238  }
239 
240  //! sets our hybridization
241  void setHybridization(HybridizationType what) { d_hybrid = what; }
242  //! returns our hybridization
244  return static_cast<HybridizationType>(d_hybrid);
245  }
246 
247  // ------------------------------------
248  // Some words of explanation before getting down into
249  // the query stuff.
250  // These query functions are really only here so that they
251  // can have real functionality in subclasses (like QueryAtoms).
252  // Since pretty much it's gonna be a mistake to call any of these
253  // (ever), we're saddling them all with a precondition which
254  // is guaranteed to fail. I'd like to have them be pure virtual,
255  // but that doesn't work since we need to be able to instantiate
256  // Atoms.
257  // ------------------------------------
258 
259  // This method can be used to distinguish query atoms from standard atoms:
260  virtual bool hasQuery() const { return false; }
261 
262  //! NOT CALLABLE
263  virtual void setQuery(QUERYATOM_QUERY *what);
264 
265  //! NOT CALLABLE
266  virtual QUERYATOM_QUERY *getQuery() const;
267  //! NOT CALLABLE
268  virtual void expandQuery(
269  QUERYATOM_QUERY *what,
271  bool maintainOrder = true);
272 
273  //! returns whether or not we match the argument
274  /*!
275  <b>Notes:</b>
276  The general rule is that if a property on this atom has a non-default
277  value,
278  the property on the other atom must have the same value.
279  The exception to this is H counts, which are ignored. These turns out to
280  be
281  impossible to handle generally, so rather than having odd and
282  hard-to-explain
283  exceptions, we ignore them entirely.
284 
285  Here are the rules for atom-atom matching:
286  | This | Other | Match | Reason
287  | CCO | CCO | Yes |
288  | CCO | CC[O-] | Yes |
289  | CC[O-] | CCO | No | Charge
290  | CC[O-] | CC[O-] | Yes |
291  | CC[OH] | CC[O-] | Yes |
292  | CC[OH] | CCOC | Yes |
293  | CCO | CCOC | Yes |
294  | CCC | CCC | Yes |
295  | CCC | CC[14C] | Yes |
296  | CC[14C] | CCC | No | Isotope
297  | CC[14C] | CC[14C] | Yes |
298  | C | OCO | Yes |
299  | [CH] | OCO | Yes |
300  | [CH2] | OCO | Yes |
301  | [CH3] | OCO | No | Radical
302  | C | O[CH2]O | Yes |
303  | [CH2] | O[CH2]O | Yes |
304  */
305  virtual bool Match(Atom const *what) const;
306 
307  //! returns the perturbation order for a list of integers
308  /*!
309 
310  This value is associated with chirality.
311 
312  \param probe a list of bond indices. This must be the same
313  length as our number of incoming bonds (our degree).
314 
315  \return the number of swaps required to convert the ordering
316  of the probe list to match the order of our incoming bonds:
317  e.g. if our incoming bond order is: <tt>[0,1,2,3]</tt>
318  \verbatim
319  getPerturbationOrder([1,0,2,3]) = 1
320  getPerturbationOrder([1,2,3,0]) = 3
321  getPerturbationOrder([1,2,0,3]) = 2
322  \endverbatim
323 
324  See the class documentation for a more detailed description
325  of our representation of chirality.
326 
327  <b>Notes:</b>
328  - requires an owning molecule
329 
330  */
331  int getPerturbationOrder(const INT_LIST &probe) const;
332 
333  //! calculates any of our lazy \c properties
334  /*!
335  <b>Notes:</b>
336  - requires an owning molecule
337  - the current lazy \c properties are implicit and explicit valence
338  */
339  void updatePropertyCache(bool strict = true);
340 
342 
343  //! calculates and returns our explicit valence
344  /*!
345  <b>Notes:</b>
346  - requires an owning molecule
347  */
348  int calcExplicitValence(bool strict = true);
349 
350  //! calculates and returns our implicit valence
351  /*!
352  <b>Notes:</b>
353  - requires an owning molecule
354  */
355  int calcImplicitValence(bool strict = true);
356 
357  AtomMonomerInfo *getMonomerInfo() { return dp_monomerInfo; }
358  const AtomMonomerInfo *getMonomerInfo() const { return dp_monomerInfo; }
359  //! takes ownership of the pointer
360  void setMonomerInfo(AtomMonomerInfo *info) { dp_monomerInfo = info; }
361 
362  //! Set the atom map Number of the atom
363  void setAtomMapNum(int mapno, bool strict = true) {
364  PRECONDITION(
365  !strict || (mapno >= 0 && mapno < 1000),
366  "atom map number out of range [0..1000], use strict=false to override");
367  if (mapno) {
368  setProp(common_properties::molAtomMapNumber, mapno);
369  } else if (hasProp(common_properties::molAtomMapNumber)) {
371  }
372  }
373  //! Gets the atom map Number of the atom, if no atom map exists, 0 is
374  //! returned.
375  int getAtomMapNum() const {
376  int mapno = 0;
377  getPropIfPresent(common_properties::molAtomMapNumber, mapno);
378  return mapno;
379  }
380 
381  protected:
382  //! sets our owning molecule
383  void setOwningMol(ROMol *other);
384  //! sets our owning molecule
385  void setOwningMol(ROMol &other) { setOwningMol(&other); }
386 
389  std::uint8_t d_numExplicitHs;
390  std::int8_t d_formalCharge;
391  std::uint8_t d_atomicNum;
392  // NOTE that these cannot be signed, they are calculated using
393  // a lazy scheme and are initialized to -1 to indicate that the
394  // calculation has not yet been done.
395  std::int8_t d_implicitValence, d_explicitValence;
396  std::uint8_t d_numRadicalElectrons;
397  std::uint8_t d_chiralTag;
398  std::uint8_t d_hybrid;
399 
400  std::uint16_t d_isotope;
402 
405  void initAtom();
406  void initFromOther(const Atom &other);
407 };
408 
409 //! Set the atom's MDL integer RLabel
410 /// Setting to 0 clears the rlabel. Rlabel must be in the range [0..99]
411 RDKIT_GRAPHMOL_EXPORT void setAtomRLabel(Atom *atm, int rlabel);
413 
414 //! Set the atom's MDL atom alias
415 /// Setting to an empty string clears the alias
416 RDKIT_GRAPHMOL_EXPORT void setAtomAlias(Atom *atom, const std::string &alias);
417 RDKIT_GRAPHMOL_EXPORT std::string getAtomAlias(const Atom *atom);
418 
419 //! Set the atom's MDL atom value
420 /// Setting to an empty string clears the value
421 /// This is where recursive smarts get stored in MolBlock Queries
422 RDKIT_GRAPHMOL_EXPORT void setAtomValue(Atom *atom, const std::string &value);
423 RDKIT_GRAPHMOL_EXPORT std::string getAtomValue(const Atom *atom);
424 
425 //! Sets the supplemental label that will follow the atom when writing
426 /// smiles strings.
428  const std::string &label);
430 }; // namespace RDKit
431 //! allows Atom objects to be dumped to streams
432 RDKIT_GRAPHMOL_EXPORT std::ostream &operator<<(std::ostream &target,
433  const RDKit::Atom &at);
434 
435 namespace RDKit {
436 //! returns whether or not the atom is to the left of C
437 RDKIT_GRAPHMOL_EXPORT bool isEarlyAtom(int atomicNum);
438 } // namespace RDKit
439 #endif
RDKIT_GRAPHMOL_EXPORT std::ostream & operator<<(std::ostream &target, const RDKit::Atom &at)
allows Atom objects to be dumped to streams
#define PRECONDITION(expr, mess)
Definition: Invariant.h:109
Pulls in all the query types.
Base class for all queries.
Definition: Query.h:45
The abstract base class for atom-level monomer info.
Definition: MonomerInfo.h:26
The class for representing atoms.
Definition: Atom.h:68
ChiralType getChiralTag() const
returns our chiralTag
Definition: Atom.h:236
void setNumExplicitHs(unsigned int what)
sets our number of explicit Hs
Definition: Atom.h:214
void initAtom()
void setHybridization(HybridizationType what)
sets our hybridization
Definition: Atom.h:241
Atom & operator=(const Atom &other)
Queries::Query< int, Atom const *, true > QUERYATOM_QUERY
Definition: Atom.h:75
bool needsUpdatePropertyCache() const
ROMol & getOwningMol() const
returns a reference to the ROMol that owns this instance
Definition: Atom.h:126
virtual void expandQuery(QUERYATOM_QUERY *what, Queries::CompositeQueryType how=Queries::COMPOSITE_AND, bool maintainOrder=true)
NOT CALLABLE.
atomindex_t d_index
Definition: Atom.h:401
bool getNoImplicit() const
returns the noImplicit flag
Definition: Atom.h:211
Atom(unsigned int num)
construct an Atom with a particular atomic number
unsigned int getIdx() const
returns our index within the ROMol
Definition: Atom.h:132
unsigned int getNumExplicitHs() const
returns our number of explicit Hs
Definition: Atom.h:216
unsigned int getNumRadicalElectrons() const
returns the number of radical electrons for this Atom
Definition: Atom.h:199
bool df_isAromatic
Definition: Atom.h:387
const AtomMonomerInfo * getMonomerInfo() const
Definition: Atom.h:358
void setNoImplicit(bool what)
sets our noImplicit flag, indicating whether or not we are allowed to have implicit Hs
Definition: Atom.h:209
Atom(const Atom &other)
ROMol * dp_mol
Definition: Atom.h:403
virtual void setQuery(QUERYATOM_QUERY *what)
NOT CALLABLE.
int getExplicitValence() const
returns the explicit valence (including Hs) of this atom
HybridizationType
store hybridization
Definition: Atom.h:78
@ SP3
Definition: Atom.h:83
@ SP3D2
Definition: Atom.h:85
@ SP
Definition: Atom.h:81
@ SP2
Definition: Atom.h:82
@ SP3D
Definition: Atom.h:84
int getImplicitValence() const
returns the implicit valence for this Atom
void updatePropertyCache(bool strict=true)
calculates any of our lazy properties
void setIdx(unsigned int index)
sets our index within the ROMol
Definition: Atom.h:139
void setAtomicNum(int newNum)
sets our atomic number
Definition: Atom.h:117
unsigned int getTotalNumHs(bool includeNeighbors=false) const
returns the total number of Hs (implicit and explicit) that this Atom is bound to
void initFromOther(const Atom &other)
int calcExplicitValence(bool strict=true)
calculates and returns our explicit valence
void setIsotope(unsigned int what)
sets our isotope number
std::uint16_t d_isotope
Definition: Atom.h:400
void setOwningMol(ROMol &other)
sets our owning molecule
Definition: Atom.h:385
void invertChirality()
inverts our chiralTag
std::uint8_t d_atomicNum
Definition: Atom.h:391
virtual Atom * copy() const
makes a copy of this Atom and returns a pointer to it.
int getAtomicNum() const
returns our atomic number
Definition: Atom.h:115
int calcImplicitValence(bool strict=true)
calculates and returns our implicit valence
ChiralType
store type of chirality
Definition: Atom.h:90
@ CHI_TETRAHEDRAL_CW
tetrahedral: clockwise rotation (SMILES @@)
Definition: Atom.h:92
@ CHI_TETRAHEDRAL_CCW
tetrahedral: counter-clockwise rotation (SMILES
Definition: Atom.h:93
unsigned int getNumImplicitHs() const
returns the number of implicit Hs this Atom is bound to
bool df_noImplicit
Definition: Atom.h:388
virtual QUERYATOM_QUERY * getQuery() const
NOT CALLABLE.
AtomMonomerInfo * getMonomerInfo()
Definition: Atom.h:357
int getPerturbationOrder(const INT_LIST &probe) const
returns the perturbation order for a list of integers
AtomMonomerInfo * dp_monomerInfo
Definition: Atom.h:404
int getAtomMapNum() const
Definition: Atom.h:375
void setAtomMapNum(int mapno, bool strict=true)
Set the atom map Number of the atom.
Definition: Atom.h:363
virtual bool hasQuery() const
Definition: Atom.h:260
void setFormalCharge(int what)
set's the formal charge of this atom
Definition: Atom.h:205
std::int8_t d_formalCharge
Definition: Atom.h:390
std::uint8_t d_hybrid
Definition: Atom.h:398
std::string getSymbol() const
returns our symbol (determined by our atomic number)
virtual bool Match(Atom const *what) const
returns whether or not we match the argument
void setChiralTag(ChiralType what)
sets our chiralTag
Definition: Atom.h:232
void setMonomerInfo(AtomMonomerInfo *info)
takes ownership of the pointer
Definition: Atom.h:360
HybridizationType getHybridization() const
returns our hybridization
Definition: Atom.h:243
bool getIsAromatic() const
returns our isAromatic flag
Definition: Atom.h:221
unsigned int getTotalValence() const
returns the total valence (implicit and explicit) for an atom
Atom(const std::string &what)
std::uint8_t d_numRadicalElectrons
Definition: Atom.h:396
void setIsAromatic(bool what)
sets our isAromatic flag, indicating whether or not we are aromatic
Definition: Atom.h:219
int getFormalCharge() const
returns the formal charge of this atom
Definition: Atom.h:203
double getMass() const
returns our mass
unsigned int getIsotope() const
returns our isotope number
Definition: Atom.h:229
unsigned int getTotalDegree() const
std::int8_t d_explicitValence
Definition: Atom.h:395
void setIdx(const U index)
overload
Definition: Atom.h:142
void setNumRadicalElectrons(unsigned int num)
Definition: Atom.h:200
bool hasOwningMol() const
returns whether or not this instance belongs to a molecule
Definition: Atom.h:123
void setOwningMol(ROMol *other)
sets our owning molecule
std::uint8_t d_chiralTag
Definition: Atom.h:397
std::uint8_t d_numExplicitHs
Definition: Atom.h:389
virtual ~Atom()
unsigned int getDegree() const
handles pickling (serializing) molecules
Definition: MolPickler.h:68
RWMol is a molecule class that is intended to be edited.
Definition: RWMol.h:32
#define RDKIT_GRAPHMOL_EXPORT
Definition: export.h:209
CompositeQueryType
Definition: QueryObjects.h:36
@ COMPOSITE_AND
Definition: QueryObjects.h:36
RDKIT_RDGENERAL_EXPORT const std::string molAtomMapNumber
Std stuff.
Definition: Abbreviations.h:18
std::list< int > INT_LIST
Definition: types.h:280
RDKIT_GRAPHMOL_EXPORT std::string getAtomValue(const Atom *atom)
RDKIT_GRAPHMOL_EXPORT std::string getAtomAlias(const Atom *atom)
RDKIT_GRAPHMOL_EXPORT void setAtomRLabel(Atom *atm, int rlabel)
RDKIT_GRAPHMOL_EXPORT std::string getSupplementalSmilesLabel(const Atom *atom)
RDKIT_GRAPHMOL_EXPORT void setAtomAlias(Atom *atom, const std::string &alias)
RDKIT_GRAPHMOL_EXPORT int getAtomRLabel(const Atom *atm)
RDKIT_GRAPHMOL_EXPORT void setAtomValue(Atom *atom, const std::string &value)
RDKIT_GRAPHMOL_EXPORT bool isEarlyAtom(int atomicNum)
returns whether or not the atom is to the left of C
std::uint32_t atomindex_t
Definition: details.h:14
RDKIT_GRAPHMOL_EXPORT void setSupplementalSmilesLabel(Atom *atom, const std::string &label)