Coverage Report

Created: 2023-06-07 06:20

/src/openbabel/include/openbabel/atom.h
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
atom.h - Handle OBAtom class.
3
4
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5
Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6
Some portions Copyright (C) 2003 by Michael Banck
7
8
This file is part of the Open Babel project.
9
For more information, see <http://openbabel.org/>
10
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation version 2 of the License.
14
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
GNU General Public License for more details.
19
***********************************************************************/
20
21
#ifndef OB_ATOM_H
22
#define OB_ATOM_H
23
24
#include <openbabel/babelconfig.h>
25
26
#ifndef OB_EXTERN
27
#  define OB_EXTERN extern
28
#endif
29
30
#include <vector>
31
#include <string>
32
33
#include <openbabel/base.h>
34
#include <openbabel/residue.h>
35
#include <openbabel/math/vector3.h>
36
37
namespace OpenBabel
38
{
39
40
  class OBBond;
41
  class OBMol;
42
43
  //! OBNodeBase is declared for backwards-compatibility with 2.0 and earlier code
44
  typedef OBAtom OBNodeBase;
45
  //! A standard iterator over a vector of bonds
46
  typedef std::vector<OBBond*>::iterator OBBondIterator;
47
  //! A standard iterator over a vector of atoms
48
  typedef std::vector<OBAtom*>::iterator OBAtomIterator;
49
50
  //ATOM Property Macros (flags)
51
  //! Atom is in a 4-membered ring
52
#define OB_4RING_ATOM     (1<<1)
53
  //! Atom is in a 3-membered ring
54
#define OB_3RING_ATOM     (1<<2)
55
  //! Atom is aromatic
56
134M
#define OB_AROMATIC_ATOM  (1<<3)
57
  //! Atom is in a ring
58
65.5M
#define OB_RING_ATOM      (1<<4)
59
  //! Atom is an electron donor
60
#define OB_DONOR_ATOM     (1<<7)
61
  //! Atom is an electron acceptor
62
#define OB_ACCEPTOR_ATOM  (1<<8)
63
64
#define SET_OR_UNSET_FLAG(X) \
65
130M
  if (value) SetFlag(X); \
66
130M
  else     UnsetFlag(X);
67
68
  // Class OBAtom
69
  // class introduction in atom.cpp
70
0
 #define OBATOM_TYPE_LEN 6
71
 class OBAPI OBAtom: public OBBase
72
    {
73
    protected:
74
      unsigned char                 _ele;       //!< atomic number (type unsigned char to minimize space -- allows for 0..255 elements)
75
      unsigned char                 _imph;      //!< number of implicit hydrogens
76
      char                          _type[OBATOM_TYPE_LEN];   //!< atomic type
77
      short                         _fcharge;   //!< formal charge
78
      unsigned short                _isotope;   //!< isotope (0 = most abundant)
79
      short                         _spinmultiplicity;//!< atomic spin, e.g., 2 for radical  1 or 3 for carbene
80
81
      unsigned int                  _idx;       //!< unique node index (GetIdx(), SetIdx())
82
      OBMol                        *_parent;    //!< parent molecule (if any)
83
      std::vector<OBBond*>          _vbond;     //!< bonds to this atom -- assumed to be one of the endpoints
84
85
      unsigned int                  _cidx;      //!< index into coordinate array
86
      unsigned short                _hyb;       //!< hybridization
87
      unsigned short                _flags;     //!< bitwise flags (e.g. aromaticity)
88
      double                        _pcharge;   //!< partial charge
89
      double                      **_c;         //!< coordinate array in double*
90
      mutable vector3               _v;         //!< coordinate vector
91
      OBResidue                    *_residue;   //!< parent residue (if applicable)
92
93
      unsigned long                 _id;        //!< unique id
94
95
      //! \return All flags
96
0
      int  GetFlag() const    {  return(_flags);  }
97
      //! Sets the bitwise @p flag
98
44.5M
      void SetFlag(int flag)  { _flags |= flag;   }
99
      //! Unsets the bitwise @p flag
100
86.4M
      void UnsetFlag(int flag) { _flags &= (~(flag)); }
101
      //! \return True of the atom has the @p flag
102
200M
      bool HasFlag(int flag)  {  return((_flags & flag) ? true : false); }
103
104
    public:
105
      enum StereoFlag {
106
107
      };
108
109
110
       //! Used internally by graph traversal algorithms
111
      bool Visit;
112
113
      //! Constructor
114
      OBAtom();
115
      //! Destructor
116
      virtual ~OBAtom();
117
      //! Assignment
118
      OBAtom &operator = (OBAtom &);
119
      //! Equivalence
120
0
      bool operator==(const OBAtom * other) const {  return (GetIdx() == other->GetIdx()); }
121
      //! Duplicate another atom. Copies all information with the exception of index
122
      //! \since version 2.2
123
      void Duplicate(OBAtom *);
124
      //! Clear all data. Calls OBBase::Clear() to handle any generic data.
125
      //! \return True if successful.
126
      bool Clear();
127
128
      //! \name Methods to set atomic information
129
      //@{
130
      //! Set atom index (i.e., in an OBMol)
131
139M
      void SetIdx(int idx)    { _idx = idx; _cidx = (idx-1)*3; }
132
72.0M
      void SetId(unsigned long id) { _id = id; }
133
      //! Set atom hybridization (i.e., 1 = sp, 2 = sp2, 3 = sp3 ...)
134
8
      void SetHyb(int hyb)    { _hyb = hyb; }
135
      //! Set atomic number
136
72.1M
      void SetAtomicNum(int atomicnum)    { _ele = (char)atomicnum; }
137
      //! Set isotope number (actual atomic weight is tabulated automatically, 0 = most abundant)
138
      void SetIsotope(unsigned int iso);
139
      //! Set the implicit hydrogen count to @p val
140
54.6M
      void SetImplicitHCount(unsigned int val)    { _imph = (unsigned char)val; }
141
      //! Set the formal charge of the atom to @p fcharge
142
111k
      void SetFormalCharge(int fcharge)   { _fcharge = fcharge; }
143
      //! Set the atomic spin to @p spin. See _spinmultiplicity
144
262k
      void SetSpinMultiplicity(short spin){ _spinmultiplicity = spin; }
145
      //! Set the atomic type symbol (see OBTypeTable and OBAtomTyper for more)
146
      void SetType(const char *type);
147
      //! Set the atomic type symbol (see OBTypeTable and OBAtomTyper for more)
148
      void SetType(const std::string &type);
149
      //! Set the partial charge to @p pcharge
150
0
      void SetPartialCharge(double pcharge){ _pcharge = pcharge; }
151
      //! Set the coordinate vector for this atom to @p v as a vector3
152
      void SetVector(const vector3 &v);
153
      //! Set the coordinate vector for this atom based on @p x @p y & @p z
154
      void SetVector(const double x,const double y,const double z);
155
      //! Set the position of this atom from a pointer-driven array of coordinates
156
67.2M
      void SetCoordPtr(double **c)        { _c = c; _cidx = (GetIdx()-1)*3; }
157
      //! Set the position of this atom based on the internal pointer array (i.e. from SetCoordPtr() )
158
      void SetVector();
159
      //! Attach an OBResidue @p res as containing this atom
160
0
      void SetResidue(OBResidue *res)     { _residue=res; }
161
      //! Attach an OBMol @p ptr as the parent container for this atom
162
72.0M
      void SetParent(OBMol *ptr)          { _parent=ptr; }
163
      //! Mark atom as being aromatic
164
85.1M
      void SetAromatic(bool value=true)                  { SET_OR_UNSET_FLAG(OB_AROMATIC_ATOM); }
165
      //! Mark an atom as belonging to at least one ring
166
45.8M
      void SetInRing(bool value=true)         { SET_OR_UNSET_FLAG(OB_RING_ATOM); }
167
      //! Clear the internal coordinate pointer
168
0
      void ClearCoordPtr()     { _c = nullptr; _cidx=0; }
169
      //@}
170
171
      //! \name Methods to retrieve atomic information
172
      //@{
173
      //! \return the formal charge for this atom
174
33.2M
      int          GetFormalCharge()  const { return(_fcharge);    }
175
      //! \return the atomic number for this atom
176
88.5M
      unsigned int GetAtomicNum()     const { return((unsigned int)_ele); }
177
      //! \return the isotope for this atom, if specified, or 0 for unspecified
178
6.13k
      unsigned short int GetIsotope() const { return(_isotope);    }
179
      //! \return the atomic spin, e.g., 0 (default) for normal atoms - note that this value is a convention,
180
      //!   2 for radical  1 or 3 for carbene
181
163k
      int          GetSpinMultiplicity() const { return(_spinmultiplicity); }
182
      //! \return the atomic mass of this atom given by standard IUPAC
183
      //!  average molar mass
184
      double     GetAtomicMass()    const;
185
      //! \return the atomic mass of this atom given by the isotope
186
      //! (default of 0 gives the most abundant isotope)
187
      double     GetExactMass()     const;
188
      //! \return the internal atom index (e.g., inside an OBMol)
189
866M
      unsigned int GetIdx()           const { return((int)_idx);  }
190
123k
      unsigned int GetIndex() const { return _idx - 1; }
191
1.68M
      unsigned long GetId() const { return _id; }
192
      //! \return the index into a pointer-driven array as used by
193
      //!   GetCoordPtr() or SetCoordPtr()
194
0
      unsigned int GetCoordinateIdx() const { return((int)_cidx); }
195
      //! \return The number of explicit bonds to this atom
196
17.0M
      unsigned int GetExplicitDegree() const { return (unsigned int)_vbond.size(); }
197
      //! \return The total number of bonds to this atom including bonds to implicit hydrogens
198
30.6M
      unsigned int GetTotalDegree() const { return (unsigned int)(_vbond.size() + _imph); }
199
      //! \return The sum of the bond orders of the explicit bonds to this atom
200
      unsigned int GetExplicitValence() const;
201
      //! \return The sum of the bond orders of all bonds to this atom including bonds to implicit hydrogens
202
      unsigned int GetTotalValence() const;
203
      //! \return The hybridization of this atom: 1 for sp, 2 for sp2, 3 for sp3, 4 for sq. planar, 5 for trig. bipy, 6 for octahedral
204
      unsigned int GetHyb()             const;
205
      //! \return The number of implicit hydrogens attached to this atom
206
4.95M
      unsigned char GetImplicitHCount() const { return _imph; };
207
      //! \return The number of non-hydrogens connected to this atom
208
      unsigned int GetHvyDegree()      const;
209
      //! \return The number of heteroatoms connected to an atom
210
      unsigned int GetHeteroDegree()   const;
211
      //! \return the atomic type (e.g., for molecular mechanics)
212
      char        *GetType();
213
214
      //! \return the x coordinate
215
0
      double      GetX() const   {        return(x());    }
216
      //! \return the y coordinate
217
0
      double      GetY() const  {        return(y());    }
218
      //! \return the z coordinate
219
0
      double      GetZ() const  {        return(z());    }
220
221
      // These methods check to see if there is a coordinate pointer
222
      // or an internal vector (e.g., SetCoordPtr())
223
      //! \return the x coordinate
224
8
      double      x() const {
225
8
        if (_c)            return((*_c)[_cidx]);
226
0
        else               return _v.x();
227
8
      }
228
      //! \return the y coordinate
229
8
      double      y() const {
230
8
        if (_c)            return((*_c)[_cidx+1]);
231
0
        else               return _v.y();
232
8
      }
233
      //! \return the z coordinate
234
4
      double      z() const {
235
4
        if (_c)            return((*_c)[_cidx+2]);
236
0
        else               return _v.z();
237
4
      }
238
      //! \return the coordinates as a double* or NULL if none.
239
      //!
240
      //! See SetCoordPtr() for more. If no coordinate pointer is used
241
      //! (e.g., only vector3), NULL will be returned.
242
0
      double     *GetCoordinate(){
243
0
        if (_c)          return(&(*_c)[_cidx]);
244
0
        else             return nullptr;
245
0
      }
246
      //! \return the coordinates as a vector3 object
247
      vector3   &GetVector();
248
      //! \return the coordinates as a vector3 object
249
      const vector3   &GetVector() const;
250
      //! \return the partial charge of this atom, calculating a Gasteiger charge if needed
251
      double     GetPartialCharge();
252
      //! \return the residue which contains this atom, or NULL if none exists
253
      OBResidue *GetResidue();
254
      //! \return the molecule which contains this atom, or NULL if none exists
255
200M
      OBMol     *GetParent()        {return((OBMol*)_parent);}
256
      //! Create a vector for a new bond from this atom, with length given by the supplied parameter
257
      //! \return success or failure
258
      bool       GetNewBondVector(vector3 &v,double length);
259
      //! \return the OBBond object between this atom and that supplied,
260
      //! or NULL if the two atoms are not bonded
261
      OBBond    *GetBond(OBAtom *);
262
      //@}
263
264
      //! \name Iterator methods
265
      //@{
266
      //! \return An iterator to the beginning of the bonds to this atom
267
      OBBondIterator BeginBonds()
268
0
        { return(_vbond.begin()); }
269
      //! \return An iterator to the end of the bonds to this atom
270
      OBBondIterator EndBonds()
271
0
        { return(_vbond.end());   }
272
      //! Set the iterator @p i to the beginning of the bonds
273
      //! \return The first bond to this atom (or NULL if none exist)
274
      OBBond *BeginBond(OBBondIterator &i);
275
      //! Increment the iterator @p i
276
      //! \return The next bond to this atom (or NULL if none exist)
277
      OBBond *NextBond(OBBondIterator &i);
278
      //! Set the iterator @p i to the beginning of the bonds
279
      //! \return The first neighboring atom (or NULL if none exist)
280
      OBAtom *BeginNbrAtom(OBBondIterator &i);
281
      //! Increment the iterator @p i
282
      //! \return The next neighboring atom (or NULL if none exist)
283
      OBAtom *NextNbrAtom(OBBondIterator &i);
284
      //@}
285
286
      //! \return the distance to the atom defined by OBMol::GetAtom()
287
      double GetDistance(int index);
288
      //! \return the distance to the supplied OBAtom
289
      double GetDistance(OBAtom*);
290
      //! \return the distance to the coordinates of the supplied vector3
291
      //! \since version 2.4
292
      double GetDistance(vector3* v);
293
      //! \return the angle defined by this atom -> b (vertex) -> c
294
      double GetAngle(int b, int c);
295
      //! \return the angle defined by this atom -> b (vertex) -> c
296
      double GetAngle(OBAtom *b, OBAtom *c);
297
298
      //! \name Addition of residue/bond info. for an atom
299
      //@{
300
301
      //! If no residue has been set for this atom, create a new one
302
      void NewResidue()
303
0
        {
304
0
          if (!_residue)
305
0
            _residue = new OBResidue;
306
0
        }
307
      //! Add (set) the residue for this atom
308
0
      void AddResidue(OBResidue *res) { SetResidue(res); }
309
      //! Delete any residue associated with this atom
310
0
      void DeleteResidue(){
311
0
        if (_residue) {
312
0
          delete _residue;
313
0
          _residue = nullptr; // Make sure to clear that a residue existed
314
0
        }
315
0
      }
316
      //! Add a bond to the internal list. Does not update the bond.
317
143M
      void AddBond(OBBond *bond) { _vbond.push_back(bond); }
318
      //! \brief Insert @p bond into the internal list at the position from @p i
319
      //! Does not modify the bond
320
      void InsertBond(OBBondIterator &i, OBBond *bond)
321
91.5k
        {
322
91.5k
          _vbond.insert(i, bond);
323
91.5k
        }
324
      //! Find @p bond and remove it from the internal list. Does not update the bond.
325
      bool DeleteBond(OBBond* bond);
326
      //! Clear all bonding information in this atom (does not delete them)
327
0
      void ClearBond() {_vbond.clear();}
328
      //@}
329
330
      //! \name Builder utilities
331
      //@{
332
333
      //! \brief If this is a hydrogen atom, transform into a methyl group
334
      //! \return success or failure
335
      bool HtoMethyl();
336
      //! Change the hybridization of this atom and modify the geometry accordingly
337
      //! \return success or failure
338
      //! \deprecated This will be removed in future versions of Open Babel
339
      OB_DEPRECATED bool SetHybAndGeom(int);
340
      //@}
341
342
      //! \name Property information
343
      //@{
344
      //! \return The number of oxygen atoms connected that only have one heavy valence
345
      unsigned int  CountFreeOxygens()      const;
346
      //! \return The number of sulfur atoms connected that only have one heavy valence
347
      //! \since version 2.4
348
      unsigned int  CountFreeSulfurs()      const;
349
      //! \return The number of hydrogens explicitly bound to this atom, optionally excluding D,T and isotope explicitly set to 1
350
      unsigned int  ExplicitHydrogenCount(bool ExcludeIsotopes=false) const;
351
      //! \return The number of rings that contain this atom
352
      unsigned int  MemberOfRingCount()     const;
353
      //! \return The size of the smallest ring that contains this atom (0 if not in a ring)
354
      unsigned int  MemberOfRingSize()    const;
355
      //! \return The number of explicit ring connections to this atom
356
      unsigned int  CountRingBonds() const;
357
      //! \return The smallest angle of bonds to this atom
358
      double    SmallestBondAngle();
359
      //! \return The average angle of bonds to this atom
360
      double    AverageBondAngle();
361
      /** Lewis acid/base vacancies for this atom
362
       *  \return A pair of integers, where first is acid count and second is base count
363
       *  \since version 2.3
364
       */
365
      std::pair<int, int> LewisAcidBaseCounts() const;
366
      //! \return Is there any residue information?
367
0
      bool HasResidue()    { return(_residue != nullptr);    }
368
      //! \return Is this a HETATM in a residue (returns false if not in a residue)
369
      //! \since version 2.4
370
0
      bool IsHetAtom() {
371
0
        if (_residue == nullptr)
372
0
          return false;
373
0
        else
374
0
          return _residue->IsHetAtom(this);
375
0
      }
376
      //! \return Is the specified element, as specified by atom number (see OBElement namespace)?
377
0
      bool IsElement(const unsigned int e) const {
378
0
           return e == _ele;
379
0
      }
380
      //! \return Is the atom aromatic?
381
      bool IsAromatic()      const;
382
      //! \return Is the atom in a ring?
383
      bool IsInRing()        const;
384
      //! \return Is the atom in a ring of a given size?
385
      bool IsInRingSize(int) const;
386
      //! \return Is this atom an element in the 15th or 16th main groups
387
      //!  (i.e., N, O, P, S ...) ?
388
      bool IsHeteroatom();
389
      //! \return Is this atom directly connected to the supplied OBAtom?
390
      bool IsConnected(OBAtom*);
391
      //! \return Is this atom related to the supplied OBAtom in
392
      //!  a 1,3 bonding pattern?
393
      bool IsOneThree(OBAtom*);
394
      //! \return Is this atom related to the supplied OBAtom in
395
      //!  a 1,4 bonding pattern?
396
      bool IsOneFour(OBAtom*);
397
      //! \return Is this atom an oxygen in a carboxyl (-CO2 or CO2H) group?
398
      bool IsCarboxylOxygen();
399
      //! \return Is this atom an oxygen in a phosphate (R-PO3) group?
400
      bool IsPhosphateOxygen();
401
      //! \return Is this atom an oxygen in a sulfate (-SO3) group?
402
      bool IsSulfateOxygen();
403
      //! \return Is this atom an oxygen in a nitro (-NO2) group?
404
      bool IsNitroOxygen();
405
      //! \return Is this atom a nitrogen in an amide (-C(=O)NR2) group?
406
      bool IsAmideNitrogen();
407
      //! \return Is this atom a hydrogen connected to a polar atom
408
      //!  (i.e., N, O, P, S)
409
      bool IsPolarHydrogen();
410
      //! \return Is this atom a hydrogen connected to a non-polar atom
411
      //!  (i.e., C)
412
      bool IsNonPolarHydrogen();
413
      //! \return Is this atom an aromatic nitrogen with at least one
414
      //!  double bond to an oxygen atom
415
      bool IsAromaticNOxide();
416
      //! \return Is this atom chiral?
417
      bool IsChiral();
418
      //! \return Is the atom part of a periodic unit cell?
419
      bool IsPeriodic() const;
420
      //! \return Is this atom an axial atom in a ring
421
      bool IsAxial();
422
      //! \return Is this atom a hydrogen-bond acceptor  (considering also atom surrounding)
423
      bool IsHbondAcceptor();
424
      //! \return Is this atom a hydrogen-bond acceptor (old function)?
425
      bool IsHbondAcceptorSimple();
426
            //! \return Is this atom a hydrogen-bond donor?
427
      bool IsHbondDonor();
428
      //! \return Is this a hydrogen atom attached to a hydrogen-bond donor?
429
      bool IsHbondDonorH();
430
      //! \return Is this atom a metal?
431
      //! \since version 2.4
432
      bool IsMetal();
433
      //! \return Whether a neighboring atom (alpha) has an unsaturated bond
434
      //!   to a third atom (beta).
435
      //! \param includePandS Whether to include phosphorus and sulfur neighbors
436
      //! in this determination (or to exclude them)
437
      bool HasAlphaBetaUnsat(bool includePandS=true);
438
      //! \return Whether this atom is connected to any bond with order == @p bo
439
      bool HasBondOfOrder(unsigned int bo);
440
      //! \return The count of bonds connected to this atom with order == @p bo
441
      int  CountBondsOfOrder(unsigned int bo);
442
      //! \return The maximum bond order for this atom
443
      int  HighestBondOrder();
444
      //! \return Whether this atom is connected to any bond with order >1
445
      bool HasNonSingleBond();
446
      //! \return Does this atom have a single bond
447
0
      bool HasSingleBond()    {        return(HasBondOfOrder(1));    }
448
      //! \return Does this atom have a double bond
449
0
      bool HasDoubleBond()    {        return(HasBondOfOrder(2));    }
450
      //! \return Does this atom have an aromatic bond
451
0
      bool HasAromaticBond()  {        return(HasBondOfOrder(5));    }
452
      //! \return Whether this atom matches the first atom in a given SMARTS pattern
453
      bool MatchesSMARTS(const char *);
454
      //@}
455
456
    }; // class OBAtom
457
458
}// namespace OpenBabel
459
460
#endif   // OB_ATOM_H
461
462
//! \file atom.h
463
//! \brief Handle atoms