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
88  } HybridizationType;
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
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
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
RDKit::isEarlyAtom
RDKIT_GRAPHMOL_EXPORT bool isEarlyAtom(int atomicNum)
returns whether or not the atom is to the left of C
RDKit::Atom::d_formalCharge
std::int8_t d_formalCharge
Definition: Atom.h:393
RDKit::Atom::getChiralTag
ChiralType getChiralTag() const
returns our chiralTag
Definition: Atom.h:239
RDKit::Atom::hasOwningMol
bool hasOwningMol() const
returns whether or not this instance belongs to a molecule
Definition: Atom.h:124
RDKit::Atom::df_noImplicit
bool df_noImplicit
Definition: Atom.h:391
RDKit::Atom::getIsotope
unsigned int getIsotope() const
returns our isotope number
Definition: Atom.h:232
RDKit::Atom::setIdx
void setIdx(const U index)
overload
Definition: Atom.h:143
RDKit::getAtomValue
RDKIT_GRAPHMOL_EXPORT std::string getAtomValue(const Atom *atom)
Queries::COMPOSITE_AND
@ COMPOSITE_AND
Definition: QueryObjects.h:36
RDKit::Atom::d_implicitValence
std::int8_t d_implicitValence
Definition: Atom.h:398
QueryObjects.h
Pulls in all the query types.
RDKit::getAtomRLabel
RDKIT_GRAPHMOL_EXPORT int getAtomRLabel(const Atom *atm)
RDKit::Atom::hasQuery
virtual bool hasQuery() const
Definition: Atom.h:263
types.h
RDKit::Atom::getNumExplicitHs
unsigned int getNumExplicitHs() const
returns our number of explict Hs
Definition: Atom.h:219
RDKit::Atom::SP
@ SP
Definition: Atom.h:82
RDKit::Atom::HybridizationType
HybridizationType
store hybridization
Definition: Atom.h:79
RDKit::AtomMonomerInfo
The abstract base class for atom-level monomer info.
Definition: MonomerInfo.h:25
Queries::CompositeQueryType
CompositeQueryType
Definition: QueryObjects.h:36
RDKit::RWMol
RWMol is a molecule class that is intended to be edited.
Definition: RWMol.h:31
RDKit::Atom::getAtomMapNum
int getAtomMapNum() const
Definition: Atom.h:378
RDKit::Atom::setOwningMol
void setOwningMol(ROMol &other)
sets our owning molecule
Definition: Atom.h:388
RDKit::Atom::ChiralType
ChiralType
store type of chirality
Definition: Atom.h:91
RDKit::setAtomRLabel
RDKIT_GRAPHMOL_EXPORT void setAtomRLabel(Atom *atm, int rlabel)
Set the atom's MDL integer RLabel.
RDKit::Atom::setAtomicNum
void setAtomicNum(int newNum)
sets our atomic number
Definition: Atom.h:118
RDKit::Atom::setAtomMapNum
void setAtomMapNum(int mapno, bool strict=true)
Set the atom map Number of the atom.
Definition: Atom.h:366
RDKit::Atom::getAtomicNum
int getAtomicNum() const
returns our atomic number
Definition: Atom.h:116
RDKit::Atom::SP3
@ SP3
Definition: Atom.h:84
RDKit::Atom::getIdx
unsigned int getIdx() const
returns our index within the ROMol
Definition: Atom.h:133
RDKit::Atom::CHI_TETRAHEDRAL_CW
@ CHI_TETRAHEDRAL_CW
tetrahedral: clockwise rotation (SMILES @@)
Definition: Atom.h:93
RDKit::setAtomAlias
RDKIT_GRAPHMOL_EXPORT void setAtomAlias(Atom *atom, const std::string &alias)
Set the atom's MDL atom alias.
RDKit::Atom
The class for representing atoms.
Definition: Atom.h:69
RDKit::Atom::setMonomerInfo
void setMonomerInfo(AtomMonomerInfo *info)
takes ownership of the pointer
Definition: Atom.h:363
RDKit::Atom::d_chiralTag
std::uint8_t d_chiralTag
Definition: Atom.h:400
RDKit::Atom::setNumRadicalElectrons
void setNumRadicalElectrons(unsigned int num)
Definition: Atom.h:201
RDKit::Atom::QUERYATOM_QUERY
Queries::Query< int, Atom const *, true > QUERYATOM_QUERY
Definition: Atom.h:76
RDKit::Atom::setIsAromatic
void setIsAromatic(bool what)
sets our isAromatic flag, indicating whether or not we are aromatic
Definition: Atom.h:222
RDKit::setSupplementalSmilesLabel
RDKIT_GRAPHMOL_EXPORT void setSupplementalSmilesLabel(Atom *atom, const std::string &label)
Sets the supplemental label that will follow the atom when writing.
RDKit::Atom::setNumExplicitHs
void setNumExplicitHs(unsigned int what)
sets our number of explict Hs
Definition: Atom.h:217
RDKit::ROMol
Definition: ROMol.h:171
RDKit::Atom::d_numExplicitHs
std::uint8_t d_numExplicitHs
Definition: Atom.h:392
RDKit::Atom::SP2
@ SP2
Definition: Atom.h:83
RDKit::Atom::d_numRadicalElectrons
std::uint8_t d_numRadicalElectrons
Definition: Atom.h:399
RDKit::Atom::getOwningMol
ROMol & getOwningMol() const
returns a reference to the ROMol that owns this instance
Definition: Atom.h:127
RDKIT_GRAPHMOL_EXPORT
#define RDKIT_GRAPHMOL_EXPORT
Definition: export.h:307
RDKit::Atom::setNoImplicit
void setNoImplicit(bool what)
sets our noImplicit flag, indicating whether or not we are allowed to have implicit Hs
Definition: Atom.h:212
RDProps.h
RDKit::Atom::d_hybrid
std::uint8_t d_hybrid
Definition: Atom.h:401
RDKit::Atom::getMonomerInfo
const AtomMonomerInfo * getMonomerInfo() const
Definition: Atom.h:361
Invariant.h
RDKit::RDProps
Definition: RDProps.h:10
RDKit::Atom::getFormalCharge
int getFormalCharge() const
returns the formal charge of this atom
Definition: Atom.h:206
RDKit::Atom::setChiralTag
void setChiralTag(ChiralType what)
sets our chiralTag
Definition: Atom.h:235
RDKit::Atom::getHybridization
HybridizationType getHybridization() const
returns our hybridization
Definition: Atom.h:246
RDKit::Atom::SP3D2
@ SP3D2
Definition: Atom.h:86
RDKit::setAtomValue
RDKIT_GRAPHMOL_EXPORT void setAtomValue(Atom *atom, const std::string &value)
Set the atom's MDL atom value.
RDKit
Std stuff.
Definition: Atom.h:30
RDKit::Atom::setIdx
void setIdx(unsigned int index)
sets our index within the ROMol
Definition: Atom.h:140
RDKit::Atom::getNoImplicit
bool getNoImplicit() const
returns the noImplicit flag
Definition: Atom.h:214
RDKit::Atom::d_atomicNum
std::uint8_t d_atomicNum
Definition: Atom.h:394
RDKit::Atom::setFormalCharge
void setFormalCharge(int what)
set's the formal charge of this atom
Definition: Atom.h:208
RDKit::Atom::S
@ S
Definition: Atom.h:81
RDKit::Atom::setHybridization
void setHybridization(HybridizationType what)
sets our hybridization
Definition: Atom.h:244
operator<<
RDKIT_GRAPHMOL_EXPORT std::ostream & operator<<(std::ostream &target, const RDKit::Atom &at)
allows Atom objects to be dumped to streams
RDKit::INT_LIST
std::list< int > INT_LIST
Definition: types.h:260
PRECONDITION
#define PRECONDITION(expr, mess)
Definition: Invariant.h:109
RDKit::MolPickler
handles pickling (serializing) molecules
Definition: MolPickler.h:63
RDKit::Atom::getNumRadicalElectrons
unsigned int getNumRadicalElectrons() const
returns the number of radical electrons for this Atom
Definition: Atom.h:200
RDKit::Atom::CHI_TETRAHEDRAL_CCW
@ CHI_TETRAHEDRAL_CCW
tetrahedral: counter-clockwise rotation (SMILES
Definition: Atom.h:94
RDKit::Atom::SP3D
@ SP3D
Definition: Atom.h:85
Queries::Query
Base class for all queries.
Definition: Query.h:46
RDKit::atomindex_t
std::uint32_t atomindex_t
Definition: details.h:14
RDKit::Atom::dp_mol
ROMol * dp_mol
Definition: Atom.h:406
details.h
RDKit::Atom::getIsAromatic
bool getIsAromatic() const
returns our isAromatic flag
Definition: Atom.h:224
RDKit::Atom::d_index
atomindex_t d_index
Definition: Atom.h:404
RDKit::Atom::d_isotope
std::uint16_t d_isotope
Definition: Atom.h:403
RDKit::Atom::dp_monomerInfo
AtomMonomerInfo * dp_monomerInfo
Definition: Atom.h:407
RDKit::getAtomAlias
RDKIT_GRAPHMOL_EXPORT std::string getAtomAlias(const Atom *atom)
RDKit::Atom::getMonomerInfo
AtomMonomerInfo * getMonomerInfo()
Definition: Atom.h:360
RDKit::common_properties::molAtomMapNumber
const RDKIT_RDGENERAL_EXPORT std::string molAtomMapNumber
RDKit::getSupplementalSmilesLabel
RDKIT_GRAPHMOL_EXPORT std::string getSupplementalSmilesLabel(const Atom *atom)
export.h