Coverage Report

Created: 2025-07-11 06:49

/src/openbabel/include/openbabel/builder.h
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
builder.h - OBBuilder class.
3
4
Copyright (C) 2007-2008 by Tim Vandermeersch
5
                           <tim.vandermeersch@gmail.com>
6
7
This file is part of the Open Babel project.
8
For more information, see <http://openbabel.org/>
9
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation version 2 of the License.
13
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
***********************************************************************/
19
20
#ifndef OB_BUILDER_H
21
#define OB_BUILDER_H
22
23
#include <vector>
24
#include <string>
25
#include <map>
26
27
#include <list>
28
#include <set>
29
30
#include <openbabel/stereo/stereo.h>
31
32
namespace OpenBabel
33
{
34
  class OBMol;
35
  class OBAtom;
36
  class OBSmartsPattern;
37
  class vector3;
38
  class OBBitVec;
39
40
  //! \class OBBuilder builder.h <openbabel/builder.h>
41
  //! \brief Class to build 3D structures
42
  class OBAPI OBBuilder {
43
    public:
44
45
0
      OBBuilder(): _keeprings(false) {}
46
47
      ///@name Call the build algorithm
48
      //@{
49
      /*! The mol object contains all connectivity information (atomic numbers, bonds, bond orders, ..)
50
       *  but no 3D coordinates. Build generates these coordinates and assigns them.
51
       *  \param mol Molecule with the connectivity (from SMILES for example). The coordinates are also
52
       *         changed in this mol.
53
       *  \param stereoWarnings Warn if the stereochemistry is incorrect (default is true)
54
       */
55
    bool Build(OBMol &mol, bool stereoWarnings = true);
56
      //@}
57
58
      ///@name Setup build parameters
59
      //@{
60
      /*! If the molecule already contains 3D coordinates, if you set KeepRings to true it will use
61
       *  retain the 3D coordinates of the rings. By default KeepRings is false, and ring conformations
62
       *  are obtained by lookup in a library of ring conformers. However, since the ring conformer library
63
       *  is not exhaustive, if the ring system is not found in the library, the resulting 3D structure can
64
       *  be poor, and require geometry optimisation before it is reasonable. If your starting point is
65
       *  a 3D structure, you can set KeepRings to true, and the conformation will be taken from the input.
66
       *  The remaining (acyclic) bonds will still all be built by the builder.
67
       */
68
0
      void SetKeepRings() { _keeprings = true; }
69
0
      void UnsetKeepRings() { _keeprings = false; }
70
      //@}
71
72
73
      //! Used by LoadFragments to check for invalid (all zero coordinates) fragments
74
      void AddRingFragment(OBSmartsPattern *sp, const std::vector<vector3> &coords);
75
      //! Load fragment info from file, if is it has not already been done
76
      void LoadFragments();
77
      std::vector<vector3> GetFragmentCoord(std::string smiles);
78
79
      /*! Get the position for a new neighbour on atom.  Returns
80
       * non-finite vector if there is no reasonable location.
81
       *  \param atom Atom for which we want a new neighbour location.
82
       *  \returns The position for the new atom.
83
       */
84
      static vector3 GetNewBondVector(OBAtom *atom);
85
      static vector3 GetNewBondVector(OBAtom *atom, double length);
86
87
      /*! Atoms a and b are part of two fragments that are not connected in mol.
88
       *  Connect will translate and rotate the fragment that contains b so that
89
       *  a and b are separated by a bond. This bond is also added.
90
       *  \param mol The molecule to be modified
91
       *  \param a Index for atom in fragment that should not be rotated.
92
       *  \param b Index for atom in fragment that should be rotated.
93
       *  \param newpos Direction for new bond between a and b
94
       *  \param bondOrder Bond order of the new bond between a and b.
95
       *  \returns true if successful or fails when failed (most likely cause
96
       *  for failing: a and b are in the same fragment, they are connected)
97
       */
98
      static bool Connect(OBMol &mol, int a, int b, vector3 &newpos, int bondOrder = 1);
99
      /*! Atoms a and b are part of two fragments that are not connected in mol.
100
       *  Connect will translate and rotate the fragment that contains b so that
101
       *  a and b are separated by a bond. This bond is also added.
102
       *  \param mol The molecule to be modified
103
       *  \param a Index for atom in fragment that should not be rotated.
104
       *  \param b Index for atom in fragment that should be rotated.
105
       *  \param bondOrder Bond order of the new bond bewtween a and b.
106
       *  \returns true if successful or fails when failed (most likely cause
107
       *  for failing: a and b are in the same fragment, they are connected)
108
       */
109
      static bool Connect(OBMol &mol, int a, int b, int bondOrder = 1);
110
      /*! Swap group b, bonded to a with group d, bonded to c. The bonds a-b and b-c cannot be
111
       *  part of a ring. Atoms a and b will not be moved. Atoms b, d and their connected atoms
112
       *  (after deleting bonds ab and cd) will be translated/rotated.
113
       *
114
       *  Example:
115
       *  \code
116
       *    \ /                            /
117
       *     b                            d
118
       *      \     /     Swap(a,b,c,d)    \     /
119
       *       a---x          ---->         a---x
120
       *      /     \     /                /     \     /
121
       *     x       c---d                x       c---b
122
       *                                               \
123
       *  \endcode
124
       *
125
       *
126
       *  This function can also be used to invert chiral centers if a and c are the same atom.
127
       *
128
       *  Example
129
       *  \code
130
       *     1                        3
131
       *     |      Swap(C,1,C,3)     |
132
       *  2>-C-<3      ----->      2>-C-<1
133
       *     |                        |
134
       *     4                        4
135
       *  \endcode
136
       */
137
      static bool Swap(OBMol &mol, int a, int b, int c, int d);
138
      /*! Atoms a and b must be bonded and this bond cannot be part of a ring. The bond will
139
       *  be broken and the smiles fragment will be inserted bewteen the two remaining fragments.
140
       *  The fragment that contains a will not be translated or rotated. Parameters c and d are
141
       *  the index in the smiles to which atoms a and b will be connected respectivly.
142
       *
143
       */
144
      //bool Insert(OBMol &mol, int a, int b, std::string smiles, int c, int d);
145
      /*! Correct double bond stereochemistry
146
       *
147
       * \returns Success or failure
148
       */
149
      static bool CorrectStereoBonds(OBMol &mol);
150
      /*! Correct stereochemistry at tetrahedral atoms with at least two non-ring
151
       * bonds. It also works for spiro atoms.
152
       *
153
       * \returns Success or failure
154
       */
155
      static bool CorrectStereoAtoms(OBMol &mol, bool warn = true);
156
      /*! Does this atom connect two rings which are not otherwise connected?
157
      */
158
      static bool IsSpiroAtom(unsigned long atomId, OBMol &mol);
159
      /*! Get the fragment to which this atom belongs.
160
       *  \param atom Atom in the fragment.
161
       *  \returns The OBBitVec defining the fragment to which a belongs.
162
       */
163
      static OBBitVec GetFragment(OBAtom *atom);
164
      static void AddNbrs(OBBitVec &fragment, OBAtom *atom);
165
166
    private:
167
      //! used to hold the fragments loaded in the constructor
168
      //static std::map<std::string, double> _torsion;
169
      static std::vector<std::string> _rigid_fragments;
170
      static std::vector<std::pair<OBSmartsPattern*, std::vector<vector3> > > _ring_fragments;
171
      static std::map<std::string, int> _rigid_fragments_index;
172
      static std::map<std::string, std::vector<vector3> > _rigid_fragments_cache;
173
      //! Connect a ring fragment to an already matched fragment. Currently only
174
      //  supports the case where the fragments overlap at a spiro atom only.
175
      static void ConnectFrags(OBMol &mol, OBMol &workmol, std::vector<int> match, std::vector<vector3> coords,
176
                               std::vector<int> pivot);
177
      //! Rotate one of the spiro rings 180 degrees
178
      static void FlipSpiro(OBMol &mol, int idx);
179
      static bool FixRingStereo(std::vector<std::pair<OBStereo::Ref, bool> > atomIds,
180
                                OBMol &mol, OBStereo::Refs &unfixedcenters);
181
      static void AddRingNbrs(OBBitVec &fragment, OBAtom *atom, OBMol &mol);
182
      static bool SwapWithVector(OBMol &mol, int a, int b, int c, const vector3 &newlocation);
183
      bool _keeprings;
184
  }; // class OBBuilder
185
186
}// namespace OpenBabel
187
188
#endif   // OB_BUILDER_H
189
190
//! \file builder.h
191
//! \brief Class to build 3D structures