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