RDKit
Open-source cheminformatics and machine learning.
Atom.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Greg Landrum and other RDKit contributors
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
29namespace RDKit {
30class ROMol;
31class RWMol;
32class 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
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
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 // NOTE: the move methods are somewhat fraught for atoms associated with
107 // molecules since the molecule will still be pointing to the original object
108 Atom(Atom &&other) = default;
109 Atom &operator=(Atom &&other) = default;
110
111 virtual ~Atom();
112
113 //! makes a copy of this Atom and returns a pointer to it.
114 /*!
115 <b>Note:</b> the caller is responsible for <tt>delete</tt>ing the result
116 */
117 virtual Atom *copy() const;
118
119 //! returns our atomic number
120 int getAtomicNum() const { return d_atomicNum; }
121 //! sets our atomic number
122 void setAtomicNum(int newNum) { d_atomicNum = newNum; }
123
124 //! returns our symbol (determined by our atomic number)
125 std::string getSymbol() const;
126
127 //! returns whether or not this instance belongs to a molecule
128 bool hasOwningMol() const { return dp_mol != nullptr; }
129
130 //! returns a reference to the ROMol that owns this instance
132 PRECONDITION(dp_mol, "no owner");
133 return *dp_mol;
134 }
135
136 //! returns our index within the ROMol
137 unsigned int getIdx() const { return d_index; }
138 //! sets our index within the ROMol
139 /*!
140 <b>Notes:</b>
141 - this makes no sense if we do not have an owning molecule
142 - the index should be <tt>< this->getOwningMol()->getNumAtoms()</tt>
143 */
144 void setIdx(unsigned int index) { d_index = index; }
145 //! overload
146 template <class U>
147 void setIdx(const U index) {
148 setIdx(rdcast<unsigned int>(index));
149 }
150 //! returns the explicit degree of the Atom (number of bonded
151 //! neighbors in the graph)
152 /*!
153 <b>Notes:</b>
154 - requires an owning molecule
155 */
156 unsigned int getDegree() const;
157
158 //! returns the total degree of the Atom (number of bonded
159 //! neighbors + number of Hs)
160 /*!
161 <b>Notes:</b>
162 - requires an owning molecule
163 */
164 unsigned int getTotalDegree() const;
165
166 //! \brief returns the total number of Hs (implicit and explicit) that
167 //! this Atom is bound to
168 /*!
169 <b>Notes:</b>
170 - requires an owning molecule
171 */
172 unsigned int getTotalNumHs(bool includeNeighbors = false) const;
173
174 //! \brief returns the total valence (implicit and explicit)
175 //! for an atom
176 /*!
177 <b>Notes:</b>
178 - requires an owning molecule
179 */
180 unsigned int getTotalValence() const;
181
182 //! returns the number of implicit Hs this Atom is bound to
183 /*!
184 <b>Notes:</b>
185 - requires an owning molecule
186 */
187 unsigned int getNumImplicitHs() const;
188
189 //! returns the explicit valence (including Hs) of this atom
191
192 //! returns the implicit valence for this Atom
193 /*!
194 <b>Notes:</b>
195 - requires an owning molecule
196 */
198
199 //! returns the number of radical electrons for this Atom
200 /*!
201 <b>Notes:</b>
202 - requires an owning molecule
203 */
204 unsigned int getNumRadicalElectrons() const { return d_numRadicalElectrons; }
205 void setNumRadicalElectrons(unsigned int num) { d_numRadicalElectrons = num; }
206
207 //! returns the formal charge of this atom
208 int getFormalCharge() const { return d_formalCharge; }
209 //! set's the formal charge of this atom
210 void setFormalCharge(int what) { d_formalCharge = what; }
211
212 //! \brief sets our \c noImplicit flag, indicating whether or not
213 //! we are allowed to have implicit Hs
214 void setNoImplicit(bool what) { df_noImplicit = what; }
215 //! returns the \c noImplicit flag
216 bool getNoImplicit() const { return df_noImplicit; }
217
218 //! sets our number of explicit Hs
219 void setNumExplicitHs(unsigned int what) { d_numExplicitHs = what; }
220 //! returns our number of explicit Hs
221 unsigned int getNumExplicitHs() const { return d_numExplicitHs; }
222
223 //! sets our \c isAromatic flag, indicating whether or not we are aromatic
224 void setIsAromatic(bool what) { df_isAromatic = what; }
225 //! returns our \c isAromatic flag
226 bool getIsAromatic() const { return df_isAromatic; }
227
228 //! returns our mass
229 double getMass() const;
230
231 //! sets our isotope number
232 void setIsotope(unsigned int what);
233 //! returns our isotope number
234 unsigned int getIsotope() const { return d_isotope; }
235
236 //! sets our \c chiralTag
237 void setChiralTag(ChiralType what) { d_chiralTag = what; }
238 //! inverts our \c chiralTag
240 //! returns our \c chiralTag
242 return static_cast<ChiralType>(d_chiralTag);
243 }
244
245 //! sets our hybridization
246 void setHybridization(HybridizationType what) { d_hybrid = what; }
247 //! returns our hybridization
249 return static_cast<HybridizationType>(d_hybrid);
250 }
251
252 // ------------------------------------
253 // Some words of explanation before getting down into
254 // the query stuff.
255 // These query functions are really only here so that they
256 // can have real functionality in subclasses (like QueryAtoms).
257 // Since pretty much it's gonna be a mistake to call any of these
258 // (ever), we're saddling them all with a precondition which
259 // is guaranteed to fail. I'd like to have them be pure virtual,
260 // but that doesn't work since we need to be able to instantiate
261 // Atoms.
262 // ------------------------------------
263
264 // This method can be used to distinguish query atoms from standard atoms:
265 virtual bool hasQuery() const { return false; }
266
267 virtual std::string getQueryType() const {return "";}
268
269 //! NOT CALLABLE
270 virtual void setQuery(QUERYATOM_QUERY *what);
271
272 //! NOT CALLABLE
273 virtual QUERYATOM_QUERY *getQuery() const;
274 //! NOT CALLABLE
275 virtual void expandQuery(
276 QUERYATOM_QUERY *what,
278 bool maintainOrder = true);
279
280 //! returns whether or not we match the argument
281 /*!
282 <b>Notes:</b>
283 The general rule is that if a property on this atom has a non-default
284 value,
285 the property on the other atom must have the same value.
286 The exception to this is H counts, which are ignored. These turns out to
287 be
288 impossible to handle generally, so rather than having odd and
289 hard-to-explain
290 exceptions, we ignore them entirely.
291
292 Here are the rules for atom-atom matching:
293 | This | Other | Match | Reason
294 | CCO | CCO | Yes |
295 | CCO | CC[O-] | Yes |
296 | CC[O-] | CCO | No | Charge
297 | CC[O-] | CC[O-] | Yes |
298 | CC[OH] | CC[O-] | Yes |
299 | CC[OH] | CCOC | Yes |
300 | CCO | CCOC | Yes |
301 | CCC | CCC | Yes |
302 | CCC | CC[14C] | Yes |
303 | CC[14C] | CCC | No | Isotope
304 | CC[14C] | CC[14C] | Yes |
305 | C | OCO | Yes |
306 | [CH] | OCO | Yes |
307 | [CH2] | OCO | Yes |
308 | [CH3] | OCO | No | Radical
309 | C | O[CH2]O | Yes |
310 | [CH2] | O[CH2]O | Yes |
311 */
312 virtual bool Match(Atom const *what) const;
313
314 //! returns the perturbation order for a list of integers
315 /*!
316
317 This value is associated with chirality.
318
319 \param probe a list of bond indices. This must be the same
320 length as our number of incoming bonds (our degree).
321
322 \return the number of swaps required to convert the ordering
323 of the probe list to match the order of our incoming bonds:
324 e.g. if our incoming bond order is: <tt>[0,1,2,3]</tt>
325 \verbatim
326 getPerturbationOrder([1,0,2,3]) = 1
327 getPerturbationOrder([1,2,3,0]) = 3
328 getPerturbationOrder([1,2,0,3]) = 2
329 \endverbatim
330
331 See the class documentation for a more detailed description
332 of our representation of chirality.
333
334 <b>Notes:</b>
335 - requires an owning molecule
336
337 */
338 int getPerturbationOrder(const INT_LIST &probe) const;
339
340 //! calculates any of our lazy \c properties
341 /*!
342 <b>Notes:</b>
343 - requires an owning molecule
344 - the current lazy \c properties are implicit and explicit valence
345 */
346 void updatePropertyCache(bool strict = true);
347
349
350 //! calculates and returns our explicit valence
351 /*!
352 <b>Notes:</b>
353 - requires an owning molecule
354 */
355 int calcExplicitValence(bool strict = true);
356
357 //! calculates and returns our implicit valence
358 /*!
359 <b>Notes:</b>
360 - requires an owning molecule
361 */
362 int calcImplicitValence(bool strict = true);
363
364 AtomMonomerInfo *getMonomerInfo() { return dp_monomerInfo; }
365 const AtomMonomerInfo *getMonomerInfo() const { return dp_monomerInfo; }
366 //! takes ownership of the pointer
367 void setMonomerInfo(AtomMonomerInfo *info) { dp_monomerInfo = info; }
368
369 //! Set the atom map Number of the atom
370 void setAtomMapNum(int mapno, bool strict = true) {
372 !strict || (mapno >= 0 && mapno < 1000),
373 "atom map number out of range [0..1000], use strict=false to override");
374 if (mapno) {
376 } else if (hasProp(common_properties::molAtomMapNumber)) {
378 }
379 }
380 //! Gets the atom map Number of the atom, if no atom map exists, 0 is
381 //! returned.
382 int getAtomMapNum() const {
383 int mapno = 0;
384 getPropIfPresent(common_properties::molAtomMapNumber, mapno);
385 return mapno;
386 }
387
388 protected:
389 //! sets our owning molecule
390 void setOwningMol(ROMol *other);
391 //! sets our owning molecule
392 void setOwningMol(ROMol &other) { setOwningMol(&other); }
393
396 std::uint8_t d_numExplicitHs;
397 std::int8_t d_formalCharge;
398 std::uint8_t d_atomicNum;
399 // NOTE that these cannot be signed, they are calculated using
400 // a lazy scheme and are initialized to -1 to indicate that the
401 // calculation has not yet been done.
402 std::int8_t d_implicitValence, d_explicitValence;
404 std::uint8_t d_chiralTag;
405 std::uint8_t d_hybrid;
406
407 std::uint16_t d_isotope;
409
412 void initAtom();
413 void initFromOther(const Atom &other);
414};
415
416//! Set the atom's MDL integer RLabel
417/// Setting to 0 clears the rlabel. Rlabel must be in the range [0..99]
420
421//! Set the atom's MDL atom alias
422/// Setting to an empty string clears the alias
423RDKIT_GRAPHMOL_EXPORT void setAtomAlias(Atom *atom, const std::string &alias);
424RDKIT_GRAPHMOL_EXPORT std::string getAtomAlias(const Atom *atom);
425
426//! Set the atom's MDL atom value
427/// Setting to an empty string clears the value
428/// This is where recursive smarts get stored in MolBlock Queries
429RDKIT_GRAPHMOL_EXPORT void setAtomValue(Atom *atom, const std::string &value);
430RDKIT_GRAPHMOL_EXPORT std::string getAtomValue(const Atom *atom);
431
432//! Sets the supplemental label that will follow the atom when writing
433/// smiles strings.
435 const std::string &label);
437}; // namespace RDKit
438//! allows Atom objects to be dumped to streams
439RDKIT_GRAPHMOL_EXPORT std::ostream &operator<<(std::ostream &target,
440 const RDKit::Atom &at);
441
442namespace RDKit {
443//! returns true if the atom is to the left of C
445//! returns true if the atom is aromatic or has an aromatic bond
447
448} // namespace RDKit
449#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
virtual Atom * copy() const
makes a copy of this Atom and returns a pointer to it.
ChiralType getChiralTag() const
returns our chiralTag
Definition: Atom.h:241
AtomMonomerInfo * getMonomerInfo()
Definition: Atom.h:364
void setNumExplicitHs(unsigned int what)
sets our number of explicit Hs
Definition: Atom.h:219
Atom & operator=(const Atom &other)
void initAtom()
void setHybridization(HybridizationType what)
sets our hybridization
Definition: Atom.h:246
ROMol & getOwningMol() const
returns a reference to the ROMol that owns this instance
Definition: Atom.h:131
Queries::Query< int, Atom const *, true > QUERYATOM_QUERY
Definition: Atom.h:75
bool needsUpdatePropertyCache() const
virtual void expandQuery(QUERYATOM_QUERY *what, Queries::CompositeQueryType how=Queries::COMPOSITE_AND, bool maintainOrder=true)
NOT CALLABLE.
atomindex_t d_index
Definition: Atom.h:408
bool getNoImplicit() const
returns the noImplicit flag
Definition: Atom.h:216
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:137
unsigned int getNumExplicitHs() const
returns our number of explicit Hs
Definition: Atom.h:221
unsigned int getNumRadicalElectrons() const
returns the number of radical electrons for this Atom
Definition: Atom.h:204
bool df_isAromatic
Definition: Atom.h:394
void setNoImplicit(bool what)
sets our noImplicit flag, indicating whether or not we are allowed to have implicit Hs
Definition: Atom.h:214
Atom(const Atom &other)
ROMol * dp_mol
Definition: Atom.h:410
virtual void setQuery(QUERYATOM_QUERY *what)
NOT CALLABLE.
virtual std::string getQueryType() const
Definition: Atom.h:267
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
Atom(Atom &&other)=default
void setIdx(unsigned int index)
sets our index within the ROMol
Definition: Atom.h:144
void setAtomicNum(int newNum)
sets our atomic number
Definition: Atom.h:122
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
const AtomMonomerInfo * getMonomerInfo() const
Definition: Atom.h:365
void setIsotope(unsigned int what)
sets our isotope number
std::uint16_t d_isotope
Definition: Atom.h:407
void setOwningMol(ROMol &other)
sets our owning molecule
Definition: Atom.h:392
void invertChirality()
inverts our chiralTag
std::uint8_t d_atomicNum
Definition: Atom.h:398
int getAtomicNum() const
returns our atomic number
Definition: Atom.h:120
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:395
int getPerturbationOrder(const INT_LIST &probe) const
returns the perturbation order for a list of integers
AtomMonomerInfo * dp_monomerInfo
Definition: Atom.h:411
int getAtomMapNum() const
Definition: Atom.h:382
void setAtomMapNum(int mapno, bool strict=true)
Set the atom map Number of the atom.
Definition: Atom.h:370
virtual bool hasQuery() const
Definition: Atom.h:265
void setFormalCharge(int what)
set's the formal charge of this atom
Definition: Atom.h:210
std::int8_t d_formalCharge
Definition: Atom.h:397
std::uint8_t d_hybrid
Definition: Atom.h:405
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:237
void setMonomerInfo(AtomMonomerInfo *info)
takes ownership of the pointer
Definition: Atom.h:367
HybridizationType getHybridization() const
returns our hybridization
Definition: Atom.h:248
bool getIsAromatic() const
returns our isAromatic flag
Definition: Atom.h:226
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:403
void setIsAromatic(bool what)
sets our isAromatic flag, indicating whether or not we are aromatic
Definition: Atom.h:224
int getFormalCharge() const
returns the formal charge of this atom
Definition: Atom.h:208
Atom & operator=(Atom &&other)=default
double getMass() const
returns our mass
unsigned int getIsotope() const
returns our isotope number
Definition: Atom.h:234
unsigned int getTotalDegree() const
std::int8_t d_explicitValence
Definition: Atom.h:402
void setIdx(const U index)
overload
Definition: Atom.h:147
virtual QUERYATOM_QUERY * getQuery() const
NOT CALLABLE.
void setNumRadicalElectrons(unsigned int num)
Definition: Atom.h:205
bool hasOwningMol() const
returns whether or not this instance belongs to a molecule
Definition: Atom.h:128
void setOwningMol(ROMol *other)
sets our owning molecule
std::uint8_t d_chiralTag
Definition: Atom.h:404
std::uint8_t d_numExplicitHs
Definition: Atom.h:396
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:217
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:283
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 bool isAromaticAtom(const Atom &atom)
returns true if the atom is aromatic or has an aromatic bond
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 true if 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)