Coverage Report

Created: 2025-10-10 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/include/openbabel/stereo/tetrahedral.h
Line
Count
Source
1
/**********************************************************************
2
  tetrahedral.h - OBTetrahedralStereo
3
4
  Copyright (C) 2009 by Tim Vandermeersch
5
6
  This file is part of the Open Babel project.
7
  For more information, see <http://openbabel.org/>
8
9
  This program is free software; you can redistribute it and/or modify
10
  it under the terms of the GNU General Public License as published by
11
  the Free Software Foundation; either version 2 of the License, or
12
  (at your option) any later version.
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
  You should have received a copy of the GNU General Public License
20
  along with this program; if not, write to the Free Software
21
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
  02110-1301, USA.
23
 **********************************************************************/
24
#ifndef OB_TETRAHEDRAL_H
25
#define OB_TETRAHEDRAL_H
26
27
#include <openbabel/stereo/tetranonplanar.h>
28
29
namespace OpenBabel {
30
31
///@addtogroup stereo Stereochemistry
32
///@{
33
/**
34
 * @class OBTetrahedralStereo tetrahedral.h <openbabel/stereo/tetrahedral.h>
35
 * @brief Class for handling and storing tetrahedral atom stereochemistry.
36
 *
37
 * The OBTetrahedralStereo class is used to represent tetrahedral atom
38
 * stereo chemistry. Before continuing reading, it is recommeded to
39
 * read the OBTetraNonPlanar documentation first. Since this
40
 * class inherits OBTetraNonPlanerStereo it should be clear that the class
41
 * stores the spacial arrangement of 4 non-planer atoms. However, for the
42
 * tetrahedral case, one additional OBStereo::Ref is needed: the atom id for
43
 * the center atom.
44
 *
45
 * The stereochemistry is set, retrieved and internally stored using the
46
 * OBTetrahedralStereo::Config struct. OBTetrahedralStereo functions as a
47
 * wrapper around the Config struct and provides functions to get a copy of
48
 * the Config struct converted to any view direction or atom and winding
49
 * (OBTetrahedralStereo::GetConfig).
50
 *
51
 * @image html tetrahedral.png
52
 *
53
 * Like all stereo classes, errors, warnings or info is reported using OBMessageHandler.
54
 *
55
 * @sa OBStereo OBStereoBase OBTetraNonPlanarStereo OBStereoFacade
56
 * @since version 2.3
57
 */
58
class OBAPI OBTetrahedralStereo : public OBTetraNonPlanarStereo
59
{
60
  public:
61
#ifndef SWIG
62
    /**
63
     * \struct Config tetrahedral.h <openbabel/stereo/tetrahedral.h>
64
     * \brief Stereochemical configuration for tetrahedral stereocenters
65
     *
66
     * The config struct represents the stereochemistry in a well defined way. For
67
     * tetrahedral stereo centers, the following data members define the special
68
     * orientation of the atoms:
69
     *
70
     * - OBStereo::Ref @p center: Atom id of the stereogenic center atom.
71
     * - OBStereo::Ref @p from/towards: Atom id (or OBStereo::ImplicitRef) for the
72
     *   atom to view from/towards.
73
     * - OBStereo::Refs @p refs: The three remaining atom ids (may also contain one
74
     *   OBStereo::NoRef element if from/towards is set to a real atom id).
75
     * - OBStereo::View @p view: Specify the viewing from or towards the atom with
76
     *   @p from/towards id.
77
     * - OBStereo::Winding @p winding: Clockwise or AntiClockwise (order in the Refs @p refs list)
78
     *
79
     * @image html tetrahedral.png
80
     *
81
     * Only @p center is specific for OBTetrahedralStereo::Config. The other
82
     * data members occur in all OBTetraNonPlanarStereo derived classes.
83
     */
84
    struct OBAPI Config
85
    {
86
      /**
87
       * Default constructor. Initializes the @p from/torards and @p center to
88
       * OBStereo::NoRef, the @p winding to OBStereo::Clockwise and @p view to
89
       * OBStereo::ViewFrom.
90
       */
91
403k
      Config() : center(OBStereo::NoRef), from(OBStereo::NoRef),
92
403k
          winding(OBStereo::Clockwise), view(OBStereo::ViewFrom),
93
403k
          specified(true)
94
403k
      {  }
95
      /**
96
       * Constructor with all parameters.
97
       *
98
       * @param _center The center (chiral) atom id.
99
       * @param from_or_towards The atom id from which to view or view towards (see @p view).
100
       * @param _refs The 3 reference ids.
101
       * @param _winding The winding for the 3 ids in @p _refs.
102
       * @param _view Specify viewing from or towards the atom with @p from_or_towards id.
103
       */
104
      Config(unsigned long _center, unsigned long from_or_towards,
105
          const OBStereo::Refs &_refs, OBStereo::Winding _winding = OBStereo::Clockwise,
106
0
          OBStereo::View _view = OBStereo::ViewFrom) : center(_center),
107
0
          from(from_or_towards), refs(_refs), winding(_winding), view(_view),
108
0
          specified(true)
109
0
      {  }
110
      /**
111
       * Equal to operator. Comparing OBTetrahedralStereo::Config structs
112
       * is done using the information stored in the struct's data members
113
       * (i.e. @p view, @p winding, @p from/towards and @p refs).
114
       *
115
       * There are a number of cases resuling in false being returned:
116
       * - The centers don't match.
117
       * - One of the Refs lists does not contain 3 elements.
118
       * - 2 or more OBStereo::ImplicitRef values in a single Config struct
119
       *
120
       * When either Config struct is unspecified (i.e. the stereochemistry
121
       * implied is accidental), true is returned.
122
       *
123
       * It doesn't matter if the two Config structs use the same view, same
124
       * from/towards Ref or the same winding. All needed conversions will be
125
       * carried out automatically (see OBTetraNonPlanerStereo::ToConfig). These
126
       * conversions ensure the spacial orientation of the 4 groups remains
127
       * unchanged.
128
       *
129
       * Another key feature is the ability to comapre Config structs regardless
130
       * of implicit (OBStereo::ImplicitRef) or explicit hydrogens. This is best
131
       * illustrated with some examples. In these examples the same ref has
132
       * already been selected as from/towards atom and both use the same winding
133
       * and view direction. We will focus on how the three remaining refs are
134
       * interpreted.
135
       *
136
       @verbatim
137
         234 == 234 // true
138
         2H4 == 234 // 3 is missing, must be the implicit --> 234 == 234 // true
139
         2H4 == 243 // same as above, but now 234 == 243 // false
140
         234 == H34 // 2 is missing, must be implicit --> 234 == 234 // true
141
       @endverbatim
142
       *
143
       * By comparing the second and third example above, it can be clearly seen
144
       * that the value of 1 Ref can actually be ignored. It's position in the
145
       * sequence (or the winding) is defined by the two explicit Ref values.
146
       *
147
       * @return True if both Config structs represent the same stereochemistry.
148
       */
149
      bool operator==(const Config &other) const;
150
      /**
151
       * Not equal to operator. This is the inverse of the Equal to operator==.
152
       *
153
       * @return True if the two Config structs represent a different stereochemistry.
154
       */
155
      bool operator!=(const Config &other) const
156
0
      {
157
0
        return !(*this == other);
158
0
      }
159
160
      /**
161
       * @name Data members defining stereochemistry.
162
       * @{
163
       */
164
      unsigned long center; //<! The center (chiral) atom id.
165
      /**
166
       * This anonymous union helps to keep code clean. Both the @p from and
167
       * @p towards data members contain the same OBStereo::Ref (same memory
168
       * address) but can be used interchangeably to match the context of
169
       * the code. The real viewing direction is specified by the @p view
170
       * data member.
171
       */
172
      union {
173
        unsigned long from; //<! The viewing from atom id.
174
        unsigned long towards; //<! The viewing towards id.
175
      };
176
      OBStereo::Refs refs; //!< The 3 reference ids.
177
      OBStereo::Winding winding; //<! The winding for the 3 reference ids.
178
      OBStereo::View view; //!< Specify viewing from or towards the atom with @p from/towards id.
179
      bool specified; //!< True if the stereochemistry is specified. When false, the described
180
                      //!< special orientation is only accidental (i.e. unspecified).
181
      //@}
182
    };
183
#endif
184
    /**
185
     * Constructor.
186
     */
187
    OBTetrahedralStereo(OBMol *mol);
188
    /**
189
     * Destructor.
190
     */
191
    virtual ~OBTetrahedralStereo();
192
193
    ///@name Tetrahedral stereochemistry
194
    ///@{
195
    /**
196
     * Get the OBStereo::Type for this object.
197
     * @return OBStereo::Tetrahedral
198
     */
199
8.00M
    OBStereo::Type GetType() const { return OBStereo::Tetrahedral; }
200
    /**
201
     * @return True if this object is valid. This object is valid if all (center, from
202
     * and ref) atom ids are set.
203
     */
204
    bool IsValid() const;
205
#ifndef SWIG
206
    /**
207
     * Set the configuration using a Config struct.
208
     */
209
    void SetConfig(const Config &config);
210
    /**
211
     * Get the configuration as Config struct.
212
     */
213
    Config GetConfig(OBStereo::Winding winding = OBStereo::Clockwise,
214
        OBStereo::View view = OBStereo::ViewFrom) const;
215
    /**
216
     * Get the configuration as Config struct viewing from/towards the specified id.
217
     */
218
    Config GetConfig(unsigned long from_or_towards,
219
        OBStereo::Winding winding = OBStereo::Clockwise,
220
        OBStereo::View view = OBStereo::ViewFrom) const;
221
#endif
222
    /**
223
     * Compare the stereochemistry stored in the Config struct with the
224
     * stereochemistry specified in the Config struct from @p other.
225
     *
226
     * @copydoc Config::operator==()
227
     */
228
    bool operator==(const OBTetrahedralStereo &other) const;
229
    /**
230
     * Not equal to operator. This is the inverse of the Equal to operator==.
231
     *
232
     * @return True if the two Config structs represent a different stereochemistry.
233
     */
234
    bool operator!=(const OBTetrahedralStereo &other) const
235
0
    {
236
0
      return !(*this == other);
237
0
    }
238
    ///@}
239
240
    /*
241
     * Implement OBGenericData::Clone().
242
     */
243
    OBGenericData* Clone(OBBase *mol) const;
244
  private:
245
    Config m_cfg; //!< internal configuration
246
};
247
///@}
248
// end addtogroup doxygen
249
250
} // namespace OpenBabel
251
252
#ifndef SWIG
253
namespace std {
254
255
///@addtogroup stereo Stereochemistry
256
///@{
257
/**
258
 * @code
259
 * OBTetrahedralStereo::Config cfg;
260
 * cfg.center = 0;
261
 * cfg.towards = 4;
262
 * cfg.refs = OBStereo::MakeRefs(1, 2, 3);
263
 * cfg.winding = OBStereo::AntiClockwise;
264
 * cfg.view = OBStereo::ViewTowards;
265
 *
266
 * OBTetrahedralStereo ts(mol);
267
 * ts.SetConfig(cfg)
268
 *
269
 * cout << "ts = " << ts << endl;
270
 *
271
 * // output
272
 * OBTetrahedralStereo(center = 0, viewTowards = 4, refs = 1 2 3, anti-clockwise)
273
 * @endcode
274
 */
275
OBAPI ostream& operator<<(ostream &out, const OpenBabel::OBTetrahedralStereo &ts);
276
/**
277
 * @code
278
 * OBTetrahedralStereo::Config cfg;
279
 * cfg.center = 0;
280
 * cfg.towards = 4;
281
 * cfg.refs = OBStereo::MakeRefs(1, 2, 3);
282
 * cfg.winding = OBStereo::AntiClockwise;
283
 * cfg.view = OBStereo::ViewTowards;
284
 *
285
 * cout << "cfg = " << cfg << endl;
286
 *
287
 * // output
288
 * OBTetrahedralStereo::Config(center = 0, viewTowards = 4, refs = 1 2 3, anti-clockwise)
289
 * @endcode
290
 */
291
OBAPI ostream& operator<<(ostream &out, const OpenBabel::OBTetrahedralStereo::Config &cfg);
292
293
///@}
294
295
} // namespace std
296
#endif // SWIG
297
298
#endif
299
300
//! \file tetrahedral.h
301
//! \brief Handle general non-planar tetrahedral stereochemistry