Coverage Report

Created: 2026-08-13 07:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/include/openbabel/mol.h
Line
Count
Source
1
/**********************************************************************
2
mol.h - Handle molecules. Declarations of OBMol, OBAtom, OBBond, OBResidue.
3
        (the main header for Open Babel)
4
5
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
6
Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
7
Some portions Copyright (C) 2003 by Michael Banck
8
9
This file is part of the Open Babel project.
10
For more information, see <http://openbabel.org/>
11
12
This program is free software; you can redistribute it and/or modify
13
it under the terms of the GNU General Public License as published by
14
the Free Software Foundation version 2 of the License.
15
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public License for more details.
20
***********************************************************************/
21
22
#ifndef OB_MOL_H
23
#define OB_MOL_H
24
25
#include <openbabel/babelconfig.h>
26
27
#ifndef OB_EXTERN
28
#  define OB_EXTERN extern
29
#endif
30
#ifndef THREAD_LOCAL
31
#ifdef SWIG
32
# define THREAD_LOCAL
33
# elif (__cplusplus >= 201103L)
34
//this is required for correct multi-threading
35
#  define THREAD_LOCAL thread_local
36
# else
37
#  define THREAD_LOCAL
38
# endif
39
#endif
40
41
#include <math.h>
42
#include <float.h>
43
44
#include <vector>
45
#include <string>
46
#include <map>
47
48
#include <openbabel/base.h>
49
50
51
namespace OpenBabel
52
{
53
  class OBAtom;
54
  class OBBond;
55
  class OBResidue;
56
  class OBRing;
57
  class OBInternalCoord;
58
  class OBConversion; //used only as a pointer
59
60
  class vector3;
61
  class OBBitVec;
62
  class OBMolAtomDFSIter;
63
  class OBChainsParser;
64
65
  typedef std::vector<OBAtom*>::iterator OBAtomIterator;
66
  typedef std::vector<OBAtom*>::const_iterator OBAtomConstIterator;
67
  typedef std::vector<OBBond*>::iterator OBBondIterator;
68
  typedef std::vector<OBResidue*>::iterator OBResidueIterator;
69
70
  // Class OBMol
71
  //MOL Property Macros (flags) -- 32+ bits
72
  //! Smallest Set of Smallest Rings (SSSR) done. See OBRing and OBMol::FindSSSR
73
5.36M
#define OB_SSSR_MOL              (1<<1)
74
  //! Ring flags have been set: See OBRing::FindRingAtomsAndBonds
75
345M
#define OB_RINGFLAGS_MOL         (1<<2)
76
  //! Aromatic flags have been set for atoms and bonds
77
615M
#define OB_AROMATIC_MOL          (1<<3)
78
  //! Atom typing has been performed. See OBAtomTyper
79
771k
#define OB_ATOMTYPES_MOL         (1<<4)
80
  //! Chirality detection has been performed.
81
1.90M
#define OB_CHIRALITY_MOL         (1<<5)
82
  //! Partial charges have been set or percieved
83
657k
#define OB_PCHARGE_MOL           (1<<6)
84
  //! Atom hybridizations have been set. See OBAtomTyper
85
21.7M
#define OB_HYBRID_MOL            (1<<8)
86
  //! Ring "closure" bonds have been set. See OBBond::IsClosure
87
139M
#define OB_CLOSURE_MOL           (1<<11)
88
  //! Hyrdogen atoms have been added where needed. See OBMol::AddHydrogens
89
9.26k
#define OB_H_ADDED_MOL           (1<<12)
90
  //! pH correction for hydrogen addition has been performed.
91
9.26k
#define OB_PH_CORRECTED_MOL      (1<<13)
92
  //! Biomolecular chains and residues have been set. See OBChainsParser
93
2.90M
#define OB_CHAINS_MOL            (1<<15)
94
  //! Total charge on this molecule has been set. See OBMol::SetTotalCharge
95
2.57M
#define OB_TCHARGE_MOL           (1<<16)
96
  //! Total spin on this molecule has been set. See OBMol::SetTotalSpinMultiplicity
97
1.90M
#define OB_TSPIN_MOL             (1<<17)
98
  //! Ring typing has been performed. See OBRingTyper
99
0
#define OB_RINGTYPES_MOL         (1<<18)
100
  //! A pattern, not a complete molecule.
101
1.55M
#define OB_PATTERN_STRUCTURE     (1<<19)
102
  //! Largest Set of Smallest Rings (LSSR) done. See OBRing and OBMol::FindLSSR
103
106k
#define OB_LSSR_MOL              (1<<20)
104
  //! SpinMultiplicities on atoms have been set in OBMol::AssignSpinMultiplicity()
105
#define OB_ATOMSPIN_MOL          (1<<21)
106
  //! Treat as reaction
107
2.57M
#define OB_REACTION_MOL          (1<<22)
108
  //! Molecule is repeating in a periodic unit cell
109
136M
#define OB_PERIODIC_MOL          (1<<23)
110
  // flags 24-32 unspecified
111
112
#define SET_OR_UNSET_FLAG(X) \
113
9.11M
  if (value) SetFlag(X); \
114
9.11M
  else     UnsetFlag(X);
115
116
0
#define OB_CURRENT_CONFORMER   -1
117
118
enum HydrogenType { AllHydrogen, PolarHydrogen, NonPolarHydrogen };
119
120
  using OBMolAtomRange = OBRange<OBAtom*>;
121
  using OBMolBondRange = OBRange<OBBond*>;
122
123
#if __cplusplus >= 202002L
124
  static_assert(std::ranges::range<OBMolAtomRange>);
125
  static_assert(std::ranges::range<OBMolBondRange>);
126
#endif
127
128
  // class introduction in mol.cpp
129
 class OBAPI OBMol: public OBBase
130
  {
131
  protected:
132
    int                           _flags; //!< bitfield of flags
133
    bool                          _autoPartialCharge;//!< Assign partial charges automatically
134
    bool                          _autoFormalCharge;//!< Assign formal charges automatically
135
    std::string                   _title;       //!< Molecule title
136
    std::vector<OBAtom*>          _vatom;       //!< vector of atoms
137
    std::vector<OBAtom*>          _atomIds;     //!< vector of atoms indexed by id
138
    std::vector<OBBond*>          _vbond;       //!< vector of bonds
139
    std::vector<OBBond*>          _bondIds;     //!< vector of bonds
140
    unsigned short int            _dimension;   //!< Dimensionality of coordinates
141
    int         _totalCharge; //!< Total charge on the molecule
142
    unsigned int                  _totalSpin;   //!< Total spin on the molecule (if not specified, assumes lowest possible spin)
143
    double                        *_c;          //!< coordinate array
144
    std::vector<double*>          _vconf;       //!< vector of conformers
145
    double                        _energy;      //!< heat of formation
146
    unsigned int                  _natoms;      //!< Number of atoms
147
    unsigned int                  _nbonds;      //!< Number of bonds
148
    std::vector<OBResidue*>       _residue;     //!< Residue information (if applicable)
149
    std::vector<OBInternalCoord*> _internals;   //!< Internal Coordinates (if applicable)
150
    unsigned short int            _mod;         //!< Number of nested calls to BeginModify()
151
152
  public:
153
154
    //! \name Initialization and data (re)size methods
155
    //@{
156
    //! Constructor
157
    OBMol();
158
    //! Copy constructor, copies atoms,bonds and OBGenericData
159
    OBMol(const OBMol &);
160
    //! Destructor
161
    virtual ~OBMol();
162
    //! Assignment, copies atoms,bonds and OBGenericData
163
    OBMol &operator=(const OBMol &mol);
164
    //! Copies atoms and bonds but not OBGenericData
165
    OBMol &operator+=(const OBMol &mol);
166
167
    //! Reserve a minimum number of atoms for internal storage
168
    //! This improves performance since the internal atom vector does not grow.
169
    //! Reservation is purely a hint, so an unreasonably large value (e.g.
170
    //! a count read from a malformed file) is silently clamped to a sane
171
    //! upper bound to avoid OOM on untrusted input.
172
    void ReserveAtoms(int natoms)
173
340k
    {
174
340k
      const int kMaxReservedAtoms = 10000000;
175
340k
      if (natoms > kMaxReservedAtoms)
176
76
        natoms = kMaxReservedAtoms;
177
340k
      if (natoms > 0 && _mod) {
178
326k
        _vatom.reserve(natoms);
179
326k
        _atomIds.reserve(natoms);
180
326k
      }
181
340k
    }
182
183
    //! Free an OBAtom pointer if defined. Does no bookkeeping
184
    //! \see DeleteAtom which ensures internal connections
185
    virtual void DestroyAtom(OBAtom*);
186
    //! Free an OBBond pointer if defined. Does no bookkeeping
187
    //! \see DeleteBond which ensures internal connections
188
    virtual void DestroyBond(OBBond*);
189
    //! Free an OBResidue pointer if defined. Does no bookkeeping
190
    //! \see DeleteResidue which ensures internal connections
191
    virtual void DestroyResidue(OBResidue*);
192
193
    //! Add the specified atom to this molecule
194
    //! \param atom        the atom to add
195
    //! \param forceNewId  whether to make a new atom Id even if the atom already has one (default is false)
196
    //! \return Whether the method was successful
197
    bool AddAtom(OBAtom& atom, bool forceNewId = false);
198
    //! Add a new atom to this molecule (like AddAtom)
199
    //! Calls BeginModify() before insertion and EndModify() after insertion
200
    bool InsertAtom(OBAtom &);
201
    //! Add a new bond to the molecule with the specified parameters
202
    //! \param beginIdx  the atom index of the "start" atom
203
    //! \param endIdx    the atom index of the "end" atom
204
    //! \param order     the bond order (see OBBond::GetBondOrder())
205
    //! \param flags     any bond flags such as stereochemistry (default = none)
206
    //! \param insertpos the position index to insert the bond (default = none)
207
    //! \return Whether the new bond creation was successful
208
    bool AddBond(int beginIdx, int endIdx, int order,
209
                 int flags=0,int insertpos=-1);
210
    //! Add the specified residue to this molecule and update connections
211
    //! \return Whether the method was successful
212
    bool AddBond(OBBond&);
213
    //! Add the specified residue to this molecule and update connections
214
    //! \return Whether the method was successful
215
    bool AddResidue(OBResidue&);
216
217
    //! Create a new OBAtom in this molecule and ensure connections
218
    //! (e.g. OBAtom::GetParent(). A new unique id will be assigned
219
    //! to this atom.
220
    OBAtom    *NewAtom();
221
    //! Create a new OBAtom in this molecule and ensure connections.
222
    //! (e.g. OBAtom::GetParent(). The @p id will be assigned to this
223
    //! atom.
224
    OBAtom    *NewAtom(unsigned long id);
225
    //! Create a new OBBond in this molecule and ensure connections
226
    //! (e.g. OBBond::GetParent(). A new unique id will be assigned
227
    //! to this bond.
228
    OBBond    *NewBond();
229
    //! Create a new OBBond in this molecule and ensure connections
230
    //! (e.g. OBBond::GetParent(). The @p id will be assigned to this
231
    //! bond.
232
    OBBond    *NewBond(unsigned long id);
233
    //! Create a new OBResidue in this molecule and ensure connections.
234
    OBResidue *NewResidue();
235
    //! Deletes an atom from this molecule and all appropriate bonds.
236
    //! Updates the molecule and atom and bond indexes accordingly.
237
    //! \warning Does not update any residues which may contain this atom
238
    //! \return Whether deletion was successful
239
    bool DeleteAtom(OBAtom*, bool destroyAtom = true);
240
    //! Deletes an bond from this molecule and updates accordingly
241
    //! \return Whether deletion was successful
242
    bool DeleteBond(OBBond*, bool destroyBond = true);
243
    //! Deletes a residue from this molecule and updates accordingly.
244
    //! \return Whether deletion was successful
245
    bool DeleteResidue(OBResidue*, bool destroyResidue = true);
246
    //@}
247
248
    //! \name Molecule modification methods
249
    //@{
250
    //! Call when making many modifications -- clears conformer/rotomer data.
251
    //! The method "turns off" perception routines, improving performance.
252
    //! Changes in molecular structure will be re-considered after modifications.
253
    virtual void BeginModify(void);
254
    //! Call when done with modificaions -- re-perceive data as needed.
255
    //! This method "turns on" perception routines and re-evaluates molecular
256
    //! structure.
257
    virtual void EndModify(bool nukePerceivedData=true);
258
    //! \return The number of nested BeginModify() calls. Used internally.
259
8.30k
    int GetMod()           {      return(_mod);    }
260
    //! Increase the number of nested BeginModify calls. Dangerous!
261
    //! Instead, properly use BeginModify as needed.
262
5.33k
    void IncrementMod()    {      _mod++;          }
263
    //! Decrease the number of nested BeginModify calls. Dangerous!
264
    //! Instead, properly use EndModify as needed.
265
5.33k
    void DecrementMod()    {      _mod--;          }
266
    //@}
267
268
    //! \name Data retrieval methods
269
    //@{
270
    //! \return the entire set of flags. (Internal use, mainly.)
271
0
    int          GetFlags() const         { return(_flags); }
272
    //! \return the title of this molecule (often the filename)
273
    //! \param replaceNewlines whether to replace any newline characters with spaces
274
    const char  *GetTitle(bool replaceNewlines = true) const;
275
    //! \return the number of atoms (i.e. OBAtom children)
276
1.69G
    unsigned int NumAtoms() const         {  return(_natoms); }
277
    //! \return the number of bonds (i.e. OBBond children)
278
12.9M
    unsigned int NumBonds() const         {  return(_nbonds); }
279
    //! \return the number of non-hydrogen atoms
280
    unsigned int NumHvyAtoms() const;
281
    //! \return the number of residues (i.e. OBResidue substituents)
282
1.98M
    unsigned int NumResidues() const      { return(static_cast<unsigned int> (_residue.size())); }
283
    //! \return the number of rotatable bonds. If sampleRingBonds is true, will include rotors within rings (see OBBond::IsRotor() for details)
284
    unsigned int NumRotors(bool sampleRingBonds=false);
285
286
    //! \return the atom at index @p idx or NULL if it does not exist.
287
    //! \warning Atom indexing will change. Use iterator methods instead.
288
    OBAtom      *GetAtom(int idx) const;
289
    //! \return the atom with @p id or NULL if it does not exist.
290
    OBAtom      *GetAtomById(unsigned long id) const;
291
    //! \return the first atom in this molecule, or NULL if none exist.
292
    //! \deprecated Will be removed in favor of more standard iterator methods
293
    OB_DEPRECATED
294
    OBAtom      *GetFirstAtom() const;
295
    //! \return the bond at index @p idx or NULL if it does not exist.
296
    //! \warning Bond indexing may change. Use iterator methods instead.
297
    OBBond      *GetBond(int idx) const;
298
    //! \return the bond with @p id or NULL if it does not exist.
299
    OBBond      *GetBondById(unsigned long id) const;
300
    //! \return the bond connecting the atom indexed by @p a and @p b or NULL if none exists.
301
    //! \warning Atom indexing will change. Use atom objects and iterators instead.
302
    OBBond      *GetBond(int a, int b) const;
303
    // The safer version of the above method
304
    //! \return the bond between the atoms @p bgn and @p end or NULL if none exists
305
    OBBond      *GetBond(OBAtom* bgn, OBAtom* end) const;
306
    //! \return the residue indexed by @p idx, or NULL if none exists
307
    //! \warning Residue indexing may change. Use iterator methods instead.
308
    OBResidue   *GetResidue(int idx) const;
309
    std::vector<OBInternalCoord*> GetInternalCoord();
310
    /*! \return the dihedral angle (in degrees) between the four atoms supplied a1-a2-a3-a4)
311
     *  WARNING: SetTorsion takes an angle in radians while GetTorsion returns it
312
     *  in degrees
313
     */
314
    double       GetTorsion(int,int,int,int);
315
    /*! \return the dihedral angle (in degrees) between the four atoms @p a, @p b, @p c, and @p d)
316
     *  WARNING: SetTorsion takes an angle in radians while GetTorsion returns it
317
     *  in degrees
318
     */
319
    double       GetTorsion(OBAtom* a,OBAtom* b,OBAtom* c,OBAtom* d);
320
    //! \return the angle (in degrees) between the three atoms @p a, @p b and @p c
321
    //!  (where  a-> b (vertex) -> c )
322
    double GetAngle(OBAtom* a, OBAtom* b, OBAtom* c);
323
    //! \return the size of the smallest ring if a and b are in the same ring, 0 otherwise
324
    //! \since version 2.4
325
    int AreInSameRing(OBAtom *a, OBAtom *b);
326
    //! \return the stochoimetric formula (e.g., C4H6O)
327
    std::string  GetFormula();
328
    //! \return the stochoimetric formula in spaced format e.g. C 4 H 6 O 1
329
    std::string  GetSpacedFormula(int ones=0, const char* sp=" ", bool implicitH = true);
330
    //! \return the heat of formation for this molecule (in kcal/mol)
331
638k
    double       GetEnergy() const { return _energy; }
332
    //! \return the standard molar mass given by IUPAC atomic masses (amu)
333
    double       GetMolWt(bool implicitH = true);
334
    //! \return the mass given by isotopes (or most abundant isotope, if not specified)
335
    double   GetExactMass(bool implicitH = true);
336
    //! \return the total charge on this molecule (i.e., 0 = neutral, +1, -1...)
337
    int    GetTotalCharge();
338
    //! \return the total spin on this molecule (i.e., 1 = singlet, 2 = doublet...)
339
    unsigned int GetTotalSpinMultiplicity();
340
    //! \return the dimensionality of coordinates (i.e., 0 = unknown or no coord, 2=2D, 3=3D)
341
1.97M
    unsigned short int GetDimension() const { return _dimension; }
342
    //! \return the set of all atomic coordinates. See OBAtom::GetCoordPtr for more
343
5.26k
    double      *GetCoordinates() { return(_c); }
344
    //! \return the Smallest Set of Smallest Rings has been run (see OBRing class)
345
    std::vector<OBRing*> &GetSSSR();
346
    //! \return the Largest Set of Smallest Rings has been run (see OBRing class)
347
    std::vector<OBRing*> &GetLSSR();
348
    //! Get the current flag for whether formal charges are set with pH correction
349
0
    bool AutomaticFormalCharge()   { return(_autoFormalCharge);  }
350
    //! Get the current flag for whether partial charges are auto-determined
351
849k
    bool AutomaticPartialCharge()  { return(_autoPartialCharge); }
352
    //@}
353
354
355
    //! \name Data modification methods
356
    //@{
357
    //! Set the title of this molecule to @p title
358
    void   SetTitle(const char *title);
359
    //! Set the title of this molecule to @p title
360
    void   SetTitle(std::string &title);
361
    //! Set the stochiometric formula for this molecule
362
    void   SetFormula(std::string molFormula);
363
    //! Set the heat of formation for this molecule (in kcal/mol)
364
0
    void   SetEnergy(double energy) { _energy = energy; }
365
    //! Set the dimension of this molecule (i.e., 0, 1 , 2, 3)
366
303k
    void   SetDimension(unsigned short int d) { _dimension = d; }
367
    //! Set the total charge of this molecule to @p charge
368
    void   SetTotalCharge(int charge);
369
    //! Set the total spin multiplicity of this molecule to @p spinMultiplicity
370
    //! Overrides the calculation from spin multiplicity of OBAtoms
371
    void   SetTotalSpinMultiplicity(unsigned int spinMultiplicity);
372
    //! Set the internal coordinates to @p int_coord
373
    //! (Does not call InternalToCartesian to update the 3D cartesian
374
    //! coordinates).
375
    //! The size of the @p int_coord has to be the same as the number of atoms
376
    //! in molecule (+ NULL at the beginning).
377
    void SetInternalCoord(std::vector<OBInternalCoord*> int_coord);
378
    //! Set the flag for determining automatic formal charges with pH (default=true)
379
    void SetAutomaticFormalCharge(bool val)
380
18.9k
    { _autoFormalCharge=val;  }
381
    //! Set the flag for determining partial charges automatically (default=true)
382
    void SetAutomaticPartialCharge(bool val)
383
2.94k
    { _autoPartialCharge=val; }
384
385
    //! Mark that aromaticity has been perceived for this molecule (see OBAromaticTyper)
386
89.6k
    void   SetAromaticPerceived(bool value = true)    { SET_OR_UNSET_FLAG(OB_AROMATIC_MOL);    }
387
    //! Mark that Smallest Set of Smallest Rings has been run (see OBRing class)
388
4.02M
    void   SetSSSRPerceived(bool value = true)        { SET_OR_UNSET_FLAG(OB_SSSR_MOL);        }
389
    //! Mark that Largest Set of Smallest Rings has been run (see OBRing class)
390
3.77M
    void   SetLSSRPerceived(bool value = true)        { SET_OR_UNSET_FLAG(OB_LSSR_MOL);        }
391
    //! Mark that rings have been perceived (see OBRing class for details)
392
289k
    void   SetRingAtomsAndBondsPerceived(bool value = true) { SET_OR_UNSET_FLAG(OB_RINGFLAGS_MOL); }
393
    //! Mark that atom types have been perceived (see OBAtomTyper for details)
394
7.72k
    void   SetAtomTypesPerceived(bool value = true)   { SET_OR_UNSET_FLAG(OB_ATOMTYPES_MOL);   }
395
    //! Mark that ring types have been perceived (see OBRingTyper for details)
396
0
    void   SetRingTypesPerceived(bool value = true)   { SET_OR_UNSET_FLAG(OB_RINGTYPES_MOL);   }
397
    //! Mark that chains and residues have been perceived (see OBChainsParser)
398
12.3k
    void   SetChainsPerceived(bool value = true)      { SET_OR_UNSET_FLAG(OB_CHAINS_MOL);      }
399
    //! Mark that chirality has been perceived
400
325k
    void   SetChiralityPerceived(bool value = true)   { SET_OR_UNSET_FLAG(OB_CHIRALITY_MOL);   }
401
    //! Mark that partial charges have been assigned
402
2.80k
    void   SetPartialChargesPerceived(bool value = true) { SET_OR_UNSET_FLAG(OB_PCHARGE_MOL);  }
403
    //! Mark that hybridization of all atoms has been assigned
404
289k
    void   SetHybridizationPerceived(bool value = true)  { SET_OR_UNSET_FLAG(OB_HYBRID_MOL);   }
405
    //! Mark that ring closure bonds have been assigned by graph traversal
406
289k
    void   SetClosureBondsPerceived(bool value = true)   { SET_OR_UNSET_FLAG(OB_CLOSURE_MOL);  }
407
    //! Mark that explicit hydrogen atoms have been added
408
409
13.8k
    void   SetHydrogensAdded(bool value = true) { SET_OR_UNSET_FLAG(OB_H_ADDED_MOL); }
410
0
    void   SetCorrectedForPH(bool value = true) { SET_OR_UNSET_FLAG(OB_PH_CORRECTED_MOL); }
411
0
    void   SetSpinMultiplicityAssigned(bool value = true) { SET_OR_UNSET_FLAG(OB_ATOMSPIN_MOL); }
412
    //! The OBMol is a pattern, not a complete molecule. Left unchanged by Clear().
413
0
    void   SetIsPatternStructure(bool value = true) { SET_OR_UNSET_FLAG(OB_PATTERN_STRUCTURE); }
414
1.01k
    void   SetIsReaction(bool value = true)               { SET_OR_UNSET_FLAG(OB_REACTION_MOL); }
415
    //! Mark that distance calculations, etc., should apply periodic boundary conditions through the minimimum image convention.
416
    //! Does not automatically recalculate bonding.
417
0
    void   SetPeriodicMol(bool value = true){ SET_OR_UNSET_FLAG(OB_PERIODIC_MOL); }
418
1.27G
    bool   HasFlag(int flag)   { return (_flags & flag) ? true : false; }
419
4.36M
    void   SetFlag(int flag)   { _flags |= flag; }
420
7.47M
    void   UnsetFlag(int flag) { _flags &= (~(flag)); }
421
0
    void   SetFlags(int flags) { _flags = flags; }
422
423
    //@}
424
425
    //! \name Molecule modification methods
426
    //@{
427
    // Description in transform.cpp (command-line transformations to this molecule)
428
    virtual OBBase*    DoTransformations(const std::map<std::string,std::string>* pOptions,OBConversion* pConv);
429
    // Ditto (documentation on transformation options)
430
    static const char* ClassDescription();
431
    //! Clear all information from a molecule except OB_PATTERN_STRUCTURE left unchanged
432
    bool Clear();
433
    //! Renumber the atoms of this molecule according to the order in the supplied vector
434
    void RenumberAtoms(std::vector<OBAtom*>&);
435
    //! Renumber the atoms of this molecule using the initial indexes in the supplied vector
436
    void RenumberAtoms(std::vector<int>);
437
    //! Set the coordinates for all atoms in this conformer.
438
    //! \sa OBMol::GetCoordinates()
439
    void SetCoordinates(double *c);
440
    //! Translate one conformer and rotate by a rotation matrix (which is returned) to the inertial frame-of-reference
441
    void ToInertialFrame(int conf, double *rmat);
442
    //! Translate all conformers to the inertial frame-of-reference
443
    void ToInertialFrame();
444
    //! Translates all conformers in the molecule by the supplied vector
445
    void Translate(const vector3 &v);
446
    //! Translates one conformer in the molecule by the supplied vector
447
    void Translate(const vector3 &v, int conf);
448
    //! Rotate all conformers using the supplied matrix @p u (a 3x3 array of double)
449
    void Rotate(const double u[3][3]);
450
    //! Rotate all conformers using the supplied matrix @p m (a linear 3x3 row-major array of double)
451
    void Rotate(const double m[9]);
452
    //! Rotate a specific conformer @p nconf using the supplied rotation matrix @p m
453
    void Rotate(const double m[9],int nconf);
454
    //! Translate to the center of all coordinates (for this conformer)
455
    void Center();
456
    //! Suppress hydrogens by converting explicit hydrogen atoms to implicit
457
    //! \return Success
458
    bool DeleteHydrogens();
459
    //! Suppress explicit hydrogen atoms on the supplied atom
460
    //! \return Success
461
    bool DeleteHydrogens(OBAtom*);
462
    //! Suppress explicit hydrogen atoms connected to a polar atom
463
    //! \see OBAtom::IsPolarHydrogen
464
    //! \since version 2.4
465
    bool DeletePolarHydrogens();
466
    //! Suppress explicit hydrogen atoms connected to a non-polar atom
467
    //! \see OBAtom::IsNonPolarHydrogen
468
    bool DeleteNonPolarHydrogens();
469
    //! Suppress the supplied atom if it is a hydrogen
470
    //! (Helper function for DeleteHydrogens)
471
    bool DeleteHydrogen(OBAtom*);
472
    //! Convert implicit hydrogens to explicit atoms in the molecular graph
473
    //! \param polaronly    Whether to add hydrogens only to polar atoms
474
    //! (i.e., not to C atoms)
475
    //! \param correctForPH Whether to call CorrectForPH() first
476
    //! \param pH The pH to use for CorrectForPH() modification
477
    //! \return Whether any hydrogens were added
478
    bool AddHydrogens(bool polaronly=false,bool correctForPH=false, double pH=7.4);
479
    //! For a particular atom, convert implicit hydrogens to explicit atoms in the molecular graph
480
    bool AddHydrogens(OBAtom*);
481
    //! For polar atoms only, convert implicit hydrogens to explicit atoms in the molecular graph
482
    bool AddPolarHydrogens();
483
    //! For non-polar atoms only, convert implicit hydrogens to explicit atoms in the molecular graph
484
    //! \since version 2.4
485
    bool AddNonPolarHydrogens();
486
    //! For polar and/or non-polar atoms, convert implicit hydrogens to explicit atoms in the molecular graph
487
    //! \since verison 2.4
488
    bool AddNewHydrogens(HydrogenType whichHydrogen, bool correctForPH=false, double pH=7.4);
489
490
    //! If @p threshold is not specified or is zero, remove all but the largest
491
    //! contiguous fragment. If @p threshold is non-zero, remove any fragments with fewer
492
    //! than @p threshold atoms.
493
    bool StripSalts(unsigned int threshold=0);
494
    //! Copies each disconnected fragment as a separate OBMol
495
    std::vector<OBMol> Separate(int StartIndex=1);
496
    //! Iterative component of Separate to copy one fragment at a time
497
    bool GetNextFragment( OpenBabel::OBMolAtomDFSIter& iter, OBMol& newMol );
498
    // docs in mol.cpp
499
    bool CopySubstructure(OBMol& newmol, OBBitVec *includeatoms, OBBitVec *excludebonds = (OBBitVec*)nullptr,
500
      unsigned int correctvalence=1,
501
      std::vector<unsigned int> *atomorder=(std::vector<unsigned int>*)nullptr,
502
      std::vector<unsigned int> *bondorder=(std::vector<unsigned int>*)nullptr);
503
    //! Converts the charged form of coordinate bonds, e.g.[N+]([O-])=O to N(=O)=O
504
    bool ConvertDativeBonds();
505
    //! Converts 5-valent N and P only. Return true if conversion occurred.
506
    //! \return has charged form of dative bonds(e.g.[N+]([O-])=O from N(=O)=O).
507
    //! \since version 2.4
508
    bool MakeDativeBonds();
509
    /** Convert zero-order bonds to single or double bonds and adjust adjacent atom
510
     *  charges in an attempt to achieve the correct valence state.
511
     *  @return Whether any modifications were made
512
     *  @since version 2.4
513
     */
514
    bool ConvertZeroBonds();
515
516
    //! Correct for pH by applying the OBPhModel transformations
517
    bool CorrectForPH(double pH=7.4);
518
    // docs in mol.cpp
519
    bool AssignSpinMultiplicity(bool NoImplicitH=false);
520
521
    //! Put the specified molecular charge on appropriate atoms.
522
    //! Assumes all the hydrogen is explicitly included in the molecule.
523
    //! \since version 2.4
524
    bool AssignTotalChargeToAtoms(int charge);
525
526
    //! \return the center of the supplied conformer @p nconf
527
    //! \see Center() to actually center all conformers at the origin
528
    vector3 Center(int nconf);
529
    /*! Set the torsion defined by these atoms, rotating bonded neighbors
530
     *  \par ang The torsion angle in radians
531
     *  WARNING: SetTorsion takes an angle in radians while GetTorsion returns it
532
     *  in degrees
533
     */
534
    void SetTorsion(OBAtom*,OBAtom*,OBAtom*,OBAtom*,double ang);
535
    //@}
536
537
    //! \name Molecule utilities and perception methods
538
    //@{
539
    //! Find Smallest Set of Smallest Rings (see OBRing class for more details)
540
    void FindSSSR();
541
    //! Find Largest Set of Smallest Rings
542
    void FindLSSR();
543
    //! Find all ring atoms and bonds. Does not need to call FindSSSR().
544
    void FindRingAtomsAndBonds();
545
    // documented in mol.cpp -- locates all atom indexes which can reach 'end'
546
    void FindChildren(std::vector<int> & children,int bgnIdx,int endIdx);
547
    // documented in mol.cpp -- locates all atoms which can reach 'end'
548
    void FindChildren(std::vector<OBAtom*>& children,OBAtom* bgn,OBAtom* end);
549
    //! Find the largest fragment in OBMol
550
    //! (which may include multiple non-connected fragments)
551
    //! \param frag   Return (by reference) a bit vector indicating the atoms
552
    //! in the largest fragment
553
    void FindLargestFragment(OBBitVec &frag);
554
    //! Sort a list of contig fragments by size from largest to smallest
555
    //! Each vector<int> contains the atom numbers of a contig fragment
556
    void ContigFragList(std::vector<std::vector<int> >&);
557
    //! Aligns atom a on p1 and atom b along p1->p2 vector
558
    void Align(OBAtom*,OBAtom*,vector3&,vector3&);
559
    //! Adds single bonds based on atom proximity
560
    void ConnectTheDots();
561
    //! Attempts to perceive multiple bonds based on geometries
562
    void PerceiveBondOrders();
563
    //! Fills out an OBAngleData with angles from the molecule
564
    void FindAngles();
565
    //! Fills out an OBTorsionData with angles from the molecule
566
    void FindTorsions();
567
    // documented in mol.cpp: graph-theoretical distance for each atom
568
    bool         GetGTDVector(std::vector<int> &);
569
    // documented in mol.cpp: graph-invariant index for each atom
570
    void         GetGIVector(std::vector<unsigned int> &);
571
    // documented in mol.cpp: calculate symmetry-unique identifiers
572
    void         GetGIDVector(std::vector<unsigned int> &);
573
    //@}
574
575
    //! \name Methods to check for existence of properties
576
    //@{
577
    //! Are there non-zero coordinates in two dimensions (i.e. X and Y)- and, if Not3D is true, no Z coordinates?
578
    bool Has2D(bool Not3D=false);
579
    //! Are there non-zero coordinates in all three dimensions (i.e. X, Y, Z)?
580
    bool Has3D();
581
    //! Are there any non-zero coordinates?
582
    bool HasNonZeroCoords();
583
    //! Has aromatic perception been performed?
584
612M
    bool HasAromaticPerceived()     { return(HasFlag(OB_AROMATIC_MOL)); }
585
    //! Has the smallest set of smallest rings (FindSSSR) been performed?
586
5.35M
    bool HasSSSRPerceived()         { return(HasFlag(OB_SSSR_MOL));     }
587
    //! Has the largest set of smallest rings (FindLSSR) been performed?
588
106k
    bool HasLSSRPerceived()         { return(HasFlag(OB_LSSR_MOL));     }
589
    //! Have ring atoms and bonds been assigned?
590
345M
    bool HasRingAtomsAndBondsPerceived(){return(HasFlag(OB_RINGFLAGS_MOL));}
591
    //! Have atom types been assigned by OBAtomTyper?
592
757k
    bool HasAtomTypesPerceived()    { return(HasFlag(OB_ATOMTYPES_MOL));}
593
    //! Have ring types been assigned by OBRingTyper?
594
0
    bool HasRingTypesPerceived()    { return(HasFlag(OB_RINGTYPES_MOL));}
595
    //! Has atom chirality been assigned?
596
1.90M
    bool HasChiralityPerceived()    { return(HasFlag(OB_CHIRALITY_MOL));}
597
    //! Have atomic Gasteiger partial charges been assigned by OBGastChrg?
598
24.8k
    bool HasPartialChargesPerceived() { return(HasFlag(OB_PCHARGE_MOL));}
599
    //! Has atomic hybridization been assigned by OBAtomTyper?
600
21.1M
    bool HasHybridizationPerceived() { return(HasFlag(OB_HYBRID_MOL));  }
601
    //! Have ring "closure" bonds been assigned? (e.g., OBBond::IsClosure())
602
139M
    bool HasClosureBondsPerceived() { return(HasFlag(OB_CLOSURE_MOL));  }
603
    //! Have biomolecule chains and residues been assigned by OBChainsParser?
604
1.69M
    bool HasChainsPerceived() { return(HasFlag(OB_CHAINS_MOL));         }
605
    //! Have hydrogens been added to the molecule?
606
9.26k
    bool HasHydrogensAdded() { return(HasFlag(OB_H_ADDED_MOL));         }
607
    //! Has the molecule been corrected for pH by CorrectForPH?
608
9.26k
    bool IsCorrectedForPH() { return(HasFlag(OB_PH_CORRECTED_MOL));     }
609
    //! Has total spin multiplicity been assigned?
610
0
    bool HasSpinMultiplicityAssigned() { return(HasFlag(OB_ATOMSPIN_MOL)); }
611
    //! Does this OBMol represent a reaction?
612
532k
    bool IsReaction()                  { return HasFlag(OB_REACTION_MOL); }
613
    //! Is this molecule periodic? Should periodic boundary conditions be applied?
614
134M
    bool IsPeriodic() { return(HasFlag(OB_PERIODIC_MOL)); }
615
616
    //! Are there any atoms in this molecule?
617
20.0M
    bool Empty()                       { return(_natoms == 0);          }
618
    //@}
619
620
    //! \name Multiple conformer member functions
621
    //@{
622
    //! \return the number of conformers in this molecule
623
8.28M
    int     NumConformers()    { return((_vconf.empty())?0:static_cast<int> (_vconf.size())); }
624
    //! Set the entire set of conformers for this molecule to @p v
625
    void    SetConformers(std::vector<double*> &v);
626
    //! Add a new set of coordinates @p f as a new conformer
627
0
    void    AddConformer(double *f)    {  _vconf.push_back(f);    }
628
    //! Set the molecule's current conformer to @p i
629
    //! Does nothing if @p i is larger than NumConformers()
630
    void    SetConformer(unsigned int i);
631
    //! Copy the conformer @p nconf into the array @p c
632
    //! \warning Does no checking to see if @p c is large enough
633
    void    CopyConformer(double* c,int nconf);
634
    //! Delete the conformer @p nconf
635
    void    DeleteConformer(int nconf);
636
    //! \return the coordinates to conformer @p i
637
0
    double  *GetConformer(int i)       {  return(_vconf[i]);      }
638
    //! Set the entire set of conformer energies
639
    void    SetEnergies(std::vector<double> &energies);
640
    //! Set the entire set of conformer energies
641
    std::vector<double> GetEnergies();
642
    //! Get the energy for conformer ci
643
    //! \par ci conformer index
644
    double  GetEnergy(int ci);
645
    //! Set the iterator to the beginning of the conformer list
646
    //! \return the array of coordinates for the first conformer
647
    double  *BeginConformer(std::vector<double*>::iterator&i)
648
0
    { i = _vconf.begin();
649
0
      return((i == _vconf.end()) ? nullptr:*i); }
650
    //! Advance the iterator to the next confomer, if possible
651
    //! \return The array of coordinates for the next conformer, or NULL if none exist
652
    double  *NextConformer(std::vector<double*>::iterator&i)
653
0
    { ++i;
654
0
      return((i == _vconf.end()) ? nullptr:*i); }
655
    //! \return the entire set of conformers for this molecule as a vector of floating point arrays
656
0
    std::vector<double*> &GetConformers() {   return(_vconf);     }
657
    //@}
658
659
    //! \name Iterator methods
660
    //@{
661
    //! \return An atom iterator pointing to the beginning of the atom list
662
4.15k
    OBAtomIterator BeginAtoms()   { return _vatom.begin(); }
663
    //! \return A constant atom iterator pointing to the beginning of the atom list
664
0
    OBAtomConstIterator CBeginAtoms() const { return _vatom.cbegin(); }
665
    //! \return An atom iterator pointing to the end of the atom list
666
4.15k
    OBAtomIterator EndAtoms() { return _vatom.begin() + NumAtoms() ; }
667
    //! \return A constant atom iterator pointing to the end of the atom list
668
0
    OBAtomConstIterator CEndAtoms() const { return _vatom.cbegin() + NumAtoms(); }
669
    //! \return A range over the atoms. This range can be used in a range-based for loop.
670
2.19M
    OBMolAtomRange GetAtoms() const { return {_vatom.begin(), _vatom.begin() + NumAtoms()}; }
671
    //! \return A bond iterator pointing to the beginning of the bond list
672
0
    OBBondIterator BeginBonds()   { return _vbond.begin(); }
673
    //! \return A bond iterator pointing to the end of the bond list
674
0
    OBBondIterator EndBonds()     { return _vbond.begin() + NumBonds() ; }
675
    //! \return A range over the bonds. This range can be used in a range-based for loop.
676
879k
    OBMolBondRange GetBonds() const { return {_vbond.begin(), _vbond.begin() + NumBonds()}; }
677
    //! \return A residue iterator pointing to the beginning of the residue list
678
0
    OBResidueIterator BeginResidues() { return _residue.begin(); }
679
    //! \return A residue iterator pointing to the end of the residue list
680
0
    OBResidueIterator EndResidues()   { return _residue.end();   }
681
682
    //! Set the iterator @p i to the beginning of the atom list
683
    //! \return the first atom (or NULL if none exist)
684
    OBAtom *BeginAtom(OBAtomIterator &i);
685
    //! Set the constant iterator @p i to the beginning of the atom list
686
    //! \return the first atom (or NULL if none exist)
687
    const OBAtom* BeginAtom(OBAtomConstIterator &i) const;
688
    //! Advance the iterator @p i to the next atom in the molecule
689
    //! \return the next atom (if any, or NULL if none exist)
690
    OBAtom *NextAtom(OBAtomIterator &i);
691
    //! Advance the const iterator @p i to the next atom in the molecule
692
    //! \return the next atom (if any, or NULL if none exist)
693
    const OBAtom* NextAtom(OBAtomConstIterator &i) const;
694
    //! Set the iterator @p i to the beginning of the bond list
695
    //! \return the first bond (or NULL if none exist)
696
    OBBond *BeginBond(OBBondIterator &i);
697
    //! Advance the iterator @p i to the next bond in the molecule
698
    //! \return the next bond (if any, or NULL if none exist)
699
    OBBond *NextBond(OBBondIterator &i);
700
    //! Set the iterator @p i to the beginning of the resdiue list
701
    //! \return the first residue (or NULL if none exist)
702
    OBResidue *BeginResidue(OBResidueIterator &i)
703
945k
    {
704
945k
      i = _residue.begin();
705
945k
      return((i == _residue.end()) ? nullptr:*i);
706
945k
    }
707
    //! Advance the iterator @p i to the next residue in the molecule
708
    //! \return the next residue (if any, or NULL if not possible)
709
    OBResidue *NextResidue(OBResidueIterator &i)
710
2.43M
    {
711
2.43M
      ++i;
712
2.43M
      return((i == _residue.end()) ? nullptr:*i);
713
2.43M
    }
714
    //! Set the iterator to the beginning of the internal coordinate list
715
    //! \return the first internal coordinate record, or NULL if none exist
716
    //! \see SetInternalCoord
717
    OBInternalCoord *BeginInternalCoord(std::vector<OBInternalCoord*>::iterator &i)
718
0
    {
719
0
      i = _internals.begin();
720
0
      return((i == _internals.end()) ? nullptr:*i);
721
0
    }
722
    //! Advance the iterator to the next internal coordinate record
723
    //! \return the next first internal coordinate record, or NULL if none exist
724
    //! \see SetInternalCoord
725
    OBInternalCoord *NextInternalCoord(std::vector<OBInternalCoord*>::iterator &i)
726
0
    {
727
0
      ++i;
728
0
      return((i == _internals.end()) ? nullptr:*i);
729
0
    }
730
    //@}
731
732
  };
733
734
  // Utility function prototypes
735
  //tokenize and Trim declarations moved to base.h
736
  // Deprecated -- use OBMessageHandler class instead (docs in obutil.cpp)
737
  OBAPI void ThrowError(char *str);
738
  // Deprecated -- use OBMessageHandler class instead (docs in obutil.cpp)
739
  OBAPI void ThrowError(std::string &str);
740
  //! Convert Cartesian XYZ to a set of OBInternalCoord coordinates
741
  OBAPI void CartesianToInternal(std::vector<OBInternalCoord*>&,OBMol&);
742
  //! Convert set of OBInternalCoord coordinates into Cartesian XYZ
743
  OBAPI void InternalToCartesian(std::vector<OBInternalCoord*>&,OBMol&);
744
  // Replace the last extension in str with a new one (docs in obutil.cpp)
745
  OBAPI std::string NewExtension(std::string&,char*);
746
747
  //! \brief Nested namespace for max_value templates
748
  namespace detail {
749
    //! \struct max_value mol.h <openbabel/mol.h>
750
    //! \brief a C++ template to return the maximum value of a type (e.g., int)
751
    template<typename T, int size = sizeof(T)>
752
    struct max_value
753
    {
754
      static const T result = (static_cast<T>(0xFF) << (size-1)*8) + max_value<T, size-1>::result;
755
    };
756
757
    //! \brief a C++ template to return the maximum value of a type (e.g., int)
758
    template<typename T>
759
    struct max_value<T, 0>
760
    {
761
      static const T result = 0;
762
    };
763
  }
764
765
  // No unique id
766
  static const unsigned long NoId = detail::max_value<unsigned long>::result;
767
768
  //Utility Macros
769
770
#ifndef BUFF_SIZE
771
2.82M
#define BUFF_SIZE 32768
772
#endif
773
774
#ifndef EQ
775
14.2k
#define EQ(a,b) (!strcmp((a), (b)))
776
#endif
777
778
#ifndef EQn
779
3.15M
#define EQn(a,b,n) (!strncmp((a), (b), (n)))
780
#endif
781
782
#ifndef SQUARE
783
408M
#define SQUARE(x) ((x)*(x))
784
#endif
785
786
#ifndef IsUnsatType
787
#define IsUnsatType(x)  (EQ(x,"Car") || EQ(x,"C2") || EQ(x,"Sox") || EQ(x,"Sac") || EQ(x,"Pac") || EQ(x,"So2"))
788
#endif
789
790
#ifndef __KCC
791
  extern "C"
792
  {
793
    OBAPI void  get_rmat(double*,double*,double*,int);
794
    OBAPI void  ob_make_rmat(double mat[3][3],double rmat[9]);
795
    OBAPI void  qtrfit (double *r,double *f,int size,double u[3][3]);
796
    OBAPI double superimpose(double*,double*,int);
797
  }
798
#else
799
  OBAPI void get_rmat(double*,double*,double*,int);
800
  OBAPI void ob_make_rmat(double mat[3][3],double rmat[9]);
801
  OBAPI void qtrfit (double *r,double *f,int size,double u[3][3]);
802
  OBAPI double superimpose(double*,double*,int);
803
#endif // __KCC
804
805
//  extern OBMol* (*CreateMolecule) (void);
806
807
} // end namespace OpenBabel
808
809
#endif // OB_MOL_H
810
811
//! \file mol.h
812
//! \brief Handle molecules. Declarations of OBMol, OBAtom, OBBond, OBResidue.
813
//!        (the main header for Open Babel)