/src/openbabel/include/openbabel/stereo/stereo.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | stereo.h - OBStereo & OBStereoBase |
3 | | |
4 | | Copyright (C) 2009-2010 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_STEREO_H |
25 | | #define OB_STEREO_H |
26 | | |
27 | | #include <openbabel/base.h> // OBGenericData |
28 | | #include <openbabel/isomorphism.h> // Automorphisms |
29 | | #include <vector> |
30 | | #include <map> |
31 | | #include <set> |
32 | | #include <climits> // UINT_MAX |
33 | | |
34 | | namespace OpenBabel { |
35 | | |
36 | | ///@addtogroup stereo Stereochemistry |
37 | | ///@{ |
38 | | |
39 | | /** |
40 | | * @class OBStereo stereo.h <openbabel/stereo/stereo.h> |
41 | | * @brief Placeholder for enums & Ref/Refs related functions. |
42 | | * |
43 | | * The OBStereo struct contains a number of enums with predefined values. |
44 | | * These are OBStereo::BondDirection, OBStereo::Type, OBStereo::Shape, |
45 | | * OBStereo::View, OBStereo::Winding. There are enums |
46 | | * which only apply to certain types of stereochemistry but having them |
47 | | * in 1 place makes it easier to remember. |
48 | | * |
49 | | * The OBStereo struct also contains typedefs and functions which |
50 | | * are crucial to fully understand how to use the OBStereoBase derived |
51 | | * classes (i.e. OBTetrahedralStereo, OBCisTransStereo, ...). Ref variables |
52 | | * and Refs lists are a way to uniquely reference atoms in the molecule. In |
53 | | * most cases these Ref variables are the same as the unique atom ids |
54 | | * (OBAtom::GetId). However, 2 special cases are provided: |
55 | | * |
56 | | * - OBStereo::NoRef: An initial value for Ref variables. The constructors of |
57 | | * the various Config structs set all refs to NoRef (Refs lists will remain |
58 | | * empty). This value is considered invalid when comparing stereochemistry. |
59 | | * - OBStereo::ImplicitRef: Can be used to replace implicit hydrogen ids. |
60 | | * Even with explicit hydrogens, it is still valid to replace the Ref of |
61 | | * the hydrogen with ImplicitRef. This flexibility also applies to |
62 | | * comparing stereochemistry. It is possible to compare stereochemistry |
63 | | * (e.g. OBTetrahedral::Config::operator==) between a Config struct with |
64 | | * an ImplicitRef and a Config struct where the Ref is the atom id of the |
65 | | * explicit hydrogen. See actual documentation for details about operator==. |
66 | | * |
67 | | * There are utility functions which make it easier to handle Refs. The most |
68 | | * frequently used one is OBStereo::MakeRefs to create lists containing 3 or |
69 | | * 4 Ref values. Formats and library use normally doesn't need the other |
70 | | * functions. |
71 | | * |
72 | | * @sa OBStereoBase OBStereoFacade |
73 | | * @since version 2.3 |
74 | | */ |
75 | | struct OBAPI OBStereo |
76 | | { |
77 | | /** |
78 | | * The various types of stereochemistry |
79 | | */ |
80 | | enum Type { |
81 | | CisTrans = (1<<0), //!< cis/trans double bond |
82 | | ExtendedCisTrans = (1<<1), //!< allene, biphenyl, ... |
83 | | SquarePlanar = (1<<2), //!< Square-planar stereochemistry |
84 | | Tetrahedral = (1<<3), //!< tetrahedral |
85 | | ExtendedTetrahedral = (1<<4), //!< extended tetrahedral |
86 | | TrigonalBipyramidal = (1<<5), //!< Trigonal-bipyramidal stereochemistry |
87 | | Octahedral = (1<<6) //!< Octahedral stereochemistry |
88 | | }; |
89 | | |
90 | | /** |
91 | | * Bond directions used by StereoFrom0D() to translate to |
92 | | * internal CisTransStereo representation. |
93 | | */ |
94 | | enum BondDirection { // Values taken from MDL format |
95 | | NotStereo = 0, |
96 | | UpBond = 1, |
97 | | DownBond = 6, |
98 | | UnknownDir = 4 |
99 | | }; |
100 | | |
101 | | /** |
102 | | * Shapes used by OBTetraPlanarStereo subclasses for |
103 | | * setting/getting reference ids. |
104 | | * |
105 | | * @image html SPshapes.png |
106 | | * @sa OBTetraPlanarStereo |
107 | | */ |
108 | | enum Shape { |
109 | | ShapeU = 1, |
110 | | ShapeZ = 2, |
111 | | Shape4 = 3 |
112 | | }; |
113 | | |
114 | | /** |
115 | | * Views used by OBTetraNonPlanarStereo subclasses for |
116 | | * setting/getting reference ids. |
117 | | * @sa OBTetraNonPlanarStereo |
118 | | */ |
119 | | enum View |
120 | | { |
121 | | ViewFrom = 1, //!< view from the atom (id parameter) towards the center atom |
122 | | ViewTowards = 2 //!< view from center atom towards the atom (id parameter) |
123 | | }; |
124 | | |
125 | | /** |
126 | | * Windings used by OBTetraNonPlanar subclasses for |
127 | | * setting/getting reference ids. |
128 | | * @sa OBTetraNonPlanar |
129 | | */ |
130 | | enum Winding { |
131 | | Clockwise = 1, //!< Clockwise winding |
132 | | AntiClockwise = 2, //!< AntiClockwise winding (or CounterClockwise) |
133 | | UnknownWinding = 3 //!< The configuration is specified as unknown (squiggly line in depiction) |
134 | | }; |
135 | | |
136 | | ///@name Ref & Refs types |
137 | | //@{ |
138 | | /** |
139 | | * All stereo classes work with variables of the type Ref to uniquely |
140 | | * identify atoms. In most cases these Ref variables are the same as the |
141 | | * unique atom ids. |
142 | | * |
143 | | * @sa OBAtom::GetId() OBStereo |
144 | | */ |
145 | | typedef unsigned long Ref; |
146 | | /** |
147 | | * Special case Ref values. |
148 | | */ |
149 | | enum { |
150 | | NoRef = UINT_MAX, //!< No Ref set (invalid Ref) |
151 | | ImplicitRef = UINT_MAX - 1 //!< Implicit Ref (i.e. hydrogen, N lone pair, ...). |
152 | | }; |
153 | | /** |
154 | | * A list (std::vector) of Ref variables. |
155 | | */ |
156 | | typedef std::vector<Ref> Refs; |
157 | | /** |
158 | | * Iterator (std::iterator) for a Refs list. |
159 | | */ |
160 | | typedef Refs::iterator RefIter; |
161 | | /** |
162 | | * Iterator (std::iterator) for a const Refs list. |
163 | | */ |
164 | | typedef Refs::const_iterator ConstRefIter; |
165 | | //@} |
166 | | |
167 | | ///@name Refs utility functions |
168 | | //@{ |
169 | | /** |
170 | | * Create a Refs list filled with @p ref1, @p ref2, @p ref3 & @p ref4. |
171 | | * @p ref4 is not added to the returned Refs if it is equal to NoRef. |
172 | | * |
173 | | * @return A Refs list containing the specified Ref values. |
174 | | */ |
175 | | static Refs MakeRefs(Ref ref1, Ref ref2, Ref ref3, Ref ref4 = NoRef) |
176 | 60 | { |
177 | 60 | Refs refs(3); |
178 | 60 | refs[0] = ref1; |
179 | 60 | refs[1] = ref2; |
180 | 60 | refs[2] = ref3; |
181 | 60 | if (ref4 != NoRef) |
182 | 60 | refs.push_back(ref4); |
183 | 60 | return refs; |
184 | 60 | } |
185 | | /** |
186 | | * Check if @p refs1 and @p refs2 contain the same Ref values regardless |
187 | | * of their order. |
188 | | * |
189 | | * @code |
190 | | * OBStereo::ContainsSameRefs(OBStereo::MakeRefs(1, 2, 3), OBStereo::MakeRefs(2, 3, 1)) // true |
191 | | * OBStereo::ContainsSameRefs(OBStereo::MakeRefs(1, 2, 3), OBStereo::MakeRefs(3, 2, 1)) // true |
192 | | * OBStereo::ContainsSameRefs(OBStereo::MakeRefs(1, 2, 3), OBStereo::MakeRefs(3, 4, 1)) // false |
193 | | * @endcode |
194 | | * |
195 | | * @return True if @p refs1 and @p refs2 contain the same Ref values. |
196 | | */ |
197 | | static bool ContainsSameRefs(const Refs &refs1, const Refs &refs2); |
198 | | /** |
199 | | * @return True if @p refs contains @p ref. |
200 | | */ |
201 | | static bool ContainsRef(const Refs &refs, unsigned long ref); |
202 | | //@} |
203 | | |
204 | | ///@name Low-level functions used by implementation. |
205 | | //@{ |
206 | | /** |
207 | | * Compute the inversion vector for @p refs and return the sum of it's |
208 | | * elements. The ith element in the inversion vector is the number of |
209 | | * element to the right of element i with a lower value. |
210 | | * |
211 | | * The number of inversions is the same as the number of interchanges |
212 | | * of consecutive elements. |
213 | | * |
214 | | * When working with 3 refs from a tetrahedral configuration: |
215 | | * @code |
216 | | * permutation inversion vector sum |
217 | | * ------------------------------------- |
218 | | * 123 0 0 0 0 (even) -> clockwise |
219 | | * 132 0 1 0 1 (odd) -> anti-clockwise |
220 | | * 213 1 0 0 1 (odd) -> anti-clockwise |
221 | | * 231 1 1 0 2 (even) -> clockwise |
222 | | * 312 2 0 0 2 (even) -> clockwise |
223 | | * 321 2 1 0 3 (odd) -> anti-clockwise |
224 | | * @endcode |
225 | | */ |
226 | | static int NumInversions(const Refs &refs); |
227 | | /** |
228 | | * Permutate element @p i with @p j in @p refs. |
229 | | * |
230 | | * @param refs The sequence with N elements to permutate. |
231 | | * @param i Element i (0...N-1) will be mutated to j and vice versa. |
232 | | * @param j Element j (0...N-1) will be mutated to i and vice versa. |
233 | | * |
234 | | * @note This method does nothing if i equals j. |
235 | | */ |
236 | | static void Permutate(Refs &refs, unsigned int i, unsigned int j); |
237 | | /** |
238 | | * Get @p refs with element @p i and @p j permutated. |
239 | | * |
240 | | * @param refs The sequence with N elements to permutate. |
241 | | * @param i Element @p i (0...N-1) will be mutated to @p j and vice versa. |
242 | | * @param j Element @p j (0...N-1) will be mutated to @p i and vice versa. |
243 | | * |
244 | | * @return @p refs with elements @p i and @p j permutated. |
245 | | * |
246 | | * @note This method does nothing if @p i equals @p j. |
247 | | */ |
248 | | static Refs Permutated(const Refs &refs, unsigned int i, unsigned int j); |
249 | | //@} |
250 | | |
251 | | }; |
252 | | |
253 | | /** |
254 | | * @struct OBStereoUnit stereo.h <openbabel/stereo/stereo.h> |
255 | | * @brief Struct representing a single stereogenic unit. |
256 | | * @since 2.3 |
257 | | */ |
258 | | struct OBStereoUnit |
259 | | { |
260 | | /** |
261 | | * Default constructor creating an invalid OBStereoUnit. The unit can be |
262 | | * made valid by setting the type, id and para data members. |
263 | | */ |
264 | | OBStereoUnit() : type(static_cast<OBStereo::Type>(0)), id(OBStereo::NoRef), para(false) |
265 | 0 | { |
266 | 0 | } |
267 | | |
268 | | /** |
269 | | * Constructor specifying all data to create a valid OBStereoUnit. |
270 | | */ |
271 | | OBStereoUnit(OBStereo::Type _type, unsigned long _id, bool _para = false) : |
272 | 1.02k | type(_type), id(_id), para(_para) |
273 | 1.02k | { |
274 | 1.02k | } |
275 | | |
276 | | OBStereo::Type type; //!< the type for this stereogenic unit |
277 | | unsigned long id; //!< the atom/bond (depends on type) unique id |
278 | | bool para; //!< para- (=ressemble) or true-stereocenter |
279 | | }; |
280 | | /** |
281 | | * @brief A single set of OBStereoUnit objects. |
282 | | * |
283 | | * This type can be used to represent all stereogenic units in a molecule and |
284 | | * is used as return type of FinStereogenicUnits(). This set is also the input |
285 | | * for many functions requiring this information (e.g. StereoFrom2D, ...). |
286 | | */ |
287 | | typedef std::vector<OBStereoUnit> OBStereoUnitSet; |
288 | | /** |
289 | | * @brief A set of sets of OBStereoUnit objects. |
290 | | * |
291 | | * This type is used for cases where there is some relationship between |
292 | | * individual OBStereoUnit objects. |
293 | | */ |
294 | | typedef std::vector<OBStereoUnitSet> OBStereoUnitSetOfSets; |
295 | | |
296 | | |
297 | | // fwd decl |
298 | | class OBMol; |
299 | | /** |
300 | | * @class OBStereoBase stereo.h <openbabel/stereo/stereo.h> |
301 | | * @brief Base class for all stereochemistry classes. |
302 | | * |
303 | | * All stereochemistry classes are derived from OBStereoBase. This class |
304 | | * inherits from OBGenericData which allows the objects to be stored in |
305 | | * the molecule. The attribute (OBGenericData::GetAttribute) is set to |
306 | | * "StereoData" and the data type is OBGenericDataType::StereoData. The |
307 | | * pure virtual OBStereoBase::GetType function must be implemented by |
308 | | * derived classes to return a type defined in OBStereo::Type. |
309 | | * |
310 | | * Use the OBStereoFacade for easy access to the derived classes. |
311 | | * |
312 | | * OBStereoBase keeps track of the OBMol object. This must always be |
313 | | * a valid (not 0 or deleted) pointer and can only be set using the |
314 | | * constructor. Subclasses can use this to get more information on bonding |
315 | | * for example. Finally, OBStereoBase also keeps track of the specified |
316 | | * flag. By default, this is always set to true. |
317 | | * |
318 | | * @sa OBStereo OBStereoFacade |
319 | | * @since version 2.3 |
320 | | */ |
321 | | class OBAPI OBStereoBase : public OBGenericData |
322 | | { |
323 | | public: |
324 | | /** |
325 | | * Constructor. By default, the stereochemistry is specified. Use |
326 | | * SetSpecified(false) for unspecified/unknown stereochemistry. |
327 | | * |
328 | | * @param mol The molecule. |
329 | | */ |
330 | | OBStereoBase(OBMol *mol) : |
331 | 3.02k | OBGenericData("StereoData", OBGenericDataType::StereoData, perceived), |
332 | 3.02k | m_mol(mol), m_specified(true) |
333 | 3.02k | { |
334 | 3.02k | } |
335 | | /** |
336 | | * Destructor. |
337 | | */ |
338 | 3.02k | virtual ~OBStereoBase() { m_mol = nullptr; } |
339 | | |
340 | | ///@name Geniric (for all OBStereo::Type) stereochemistry |
341 | | //@{ |
342 | | /** |
343 | | * Get the molecule. This can be used by subclasses when more |
344 | | * information is needed (e.g. OBCisTransStereo::GetCisRef, ...). |
345 | | */ |
346 | 0 | OBMol* GetMolecule() const { return m_mol; } |
347 | | /** |
348 | | * Reimplemented by subclasses to return the type defined in OBStereo::Type. |
349 | | */ |
350 | | virtual OBStereo::Type GetType() const = 0; |
351 | | /** |
352 | | * Set whether the stereochemistry is specified. Comparing a specified |
353 | | * OBStereoBase derived class (or it's Config struct) with an unspecified |
354 | | * one, always returns true. |
355 | | */ |
356 | 0 | void SetSpecified(bool specified) { m_specified = specified; } |
357 | | /** |
358 | | * @return True if the stereochemistry is specified. |
359 | | */ |
360 | 0 | bool IsSpecified() const { return m_specified; } |
361 | | //@} |
362 | | private: |
363 | | OBMol *m_mol; //!< The parent molecule. |
364 | | bool m_specified; //!< True if the stereochemistry is specified, false if unknown/unspecified. |
365 | | }; |
366 | | |
367 | | // fwd decl |
368 | | class OBTetrahedralStereo; |
369 | | class OBCisTransStereo; |
370 | | class OBSquarePlanarStereo; |
371 | | /** |
372 | | * @class OBStereoFacade stereo.h <openbabel/stereo/stereo.h> |
373 | | * @brief Facade to simplify retrieval of OBStereoBase derived objects. |
374 | | * |
375 | | * The OBStereoFacade helps with retrieving OBStereoBase derived objects |
376 | | * (i.e. OBTetrahedralStereo, OBCisTransStereo, ...) from an OBMol. This |
377 | | * is done by iterating over all OBGenericData objects with data type |
378 | | * OBGenericDataType::StereoData and checking the OBStereo::Type using |
379 | | * OBStereoBase::GetType. |
380 | | * |
381 | | * @sa OBStereo OBStereoBase |
382 | | * @since version 2.3 |
383 | | */ |
384 | | class OBAPI OBStereoFacade |
385 | | { |
386 | | public: |
387 | | /** |
388 | | * Constructor with @p mol and @p perceive parameter. |
389 | | * |
390 | | * @param mol The molecule. |
391 | | * @param perceive If true, PerceiveStereo will be called if the |
392 | | * OBMol::HasChiralityPerceived() flag is not set. (default is true) |
393 | | */ |
394 | | OBStereoFacade(OBMol *mol, bool perceive = true) : |
395 | 8.14k | m_mol(mol), m_init(false), m_perceive(perceive) |
396 | 8.14k | { |
397 | 8.14k | } |
398 | | |
399 | | ///@name Tetrahedral stereochemistry |
400 | | ///@{ |
401 | | /** |
402 | | * Get the number of tetrahedral stereocenters. |
403 | | */ |
404 | | unsigned int NumTetrahedralStereo(); |
405 | | /** |
406 | | * Get all the OBTetrahedralStereo objects. |
407 | | */ |
408 | | std::vector<OBTetrahedralStereo*> GetAllTetrahedralStereo(); |
409 | | /** |
410 | | * Check if atom with @p id is a tetrahedral center. |
411 | | * @return True if the atom with @p id has tetrahedral stereochemistry. |
412 | | */ |
413 | | bool HasTetrahedralStereo(unsigned long atomId); |
414 | | /** |
415 | | * Get the OBTetrahedralStereo object with @p atomId as center. This |
416 | | * function returns 0 if there is no OBTetrahedralStereo object found |
417 | | * with the specified center. |
418 | | */ |
419 | | OBTetrahedralStereo* GetTetrahedralStereo(unsigned long atomId); |
420 | | ///@} |
421 | | |
422 | | ///@name Cis/Trans stereochemistry |
423 | | ///@{ |
424 | | /** |
425 | | * Get the number of cis/trans stereocenters. |
426 | | */ |
427 | | unsigned int NumCisTransStereo(); |
428 | | /** |
429 | | * Get all the OBCisTransStereo objects. |
430 | | */ |
431 | | std::vector<OBCisTransStereo*> GetAllCisTransStereo(); |
432 | | /** |
433 | | * Check if bond with @p id is a stereogenic cis/trans double bond. |
434 | | * @return True if the bond with @p id has cis/trans stereochemistry. |
435 | | */ |
436 | | bool HasCisTransStereo(unsigned long bondId); |
437 | | /** |
438 | | * Get the OBTetrahedralStereo object with @p bondId as double bond. |
439 | | * This function returns 0 if there is no OBCisTransStereo object found |
440 | | * with the specified bond. |
441 | | */ |
442 | | OBCisTransStereo* GetCisTransStereo(unsigned long bondId); |
443 | | ///@} |
444 | | |
445 | | ///@name SquarePlanar stereochemistry |
446 | | ///@{ |
447 | | /** |
448 | | * Get the number of square-planar stereocenters. |
449 | | */ |
450 | | unsigned int NumSquarePlanarStereo(); |
451 | | /** |
452 | | * Get all the OBSquarePlanarStereo objects. |
453 | | */ |
454 | | std::vector<OBSquarePlanarStereo*> GetAllSquarePlanarStereo(); |
455 | | /** |
456 | | * Check if atom with @p id is a stereogenic square-planar atom. |
457 | | * @return True if the atom with @p id has square-planar stereochemistry. |
458 | | */ |
459 | | bool HasSquarePlanarStereo(unsigned long atomId); |
460 | | /** |
461 | | * Get the OBSquarePlanarStereo object with @p atomId as center. This |
462 | | * function returns 0 if there is no OBSquarePlanarStereo object found |
463 | | * with the specified center. |
464 | | */ |
465 | | OBSquarePlanarStereo* GetSquarePlanarStereo(unsigned long atomId); |
466 | | ///@} |
467 | | |
468 | | template<int StereoType> |
469 | | bool HasStereo(unsigned long id); |
470 | | template<typename T> |
471 | | T* GetStereo(unsigned long id); |
472 | | |
473 | | |
474 | | private: |
475 | | /** |
476 | | * Ensure the maps are initialized and initialize them only once. |
477 | | */ |
478 | 19.3k | inline void EnsureInit() { if (!m_init) InitMaps(); } |
479 | | /** |
480 | | * Initialize @p m_tetrahedralMap and m_cistransMap to contain the |
481 | | * data objects. If @p m_perceive is true and chirality isn't perceived |
482 | | * yet, PerceiveStereo will be called. |
483 | | */ |
484 | | void InitMaps(); |
485 | | |
486 | | OBMol *m_mol; |
487 | | bool m_init; |
488 | | bool m_perceive; |
489 | | std::map<unsigned long, OBTetrahedralStereo*> m_tetrahedralMap; |
490 | | std::map<unsigned long, OBCisTransStereo*> m_cistransMap; |
491 | | std::map<unsigned long, OBSquarePlanarStereo*> m_squarePlanarMap; |
492 | | }; |
493 | | |
494 | | // fwd decl |
495 | | class OBBond; |
496 | | ///@name High level functions |
497 | | ///@{ |
498 | | /** |
499 | | * Convert 0D/2D/3D coordinates to OBStereo objects. The right function will |
500 | | * be selected based on the molecule's dimensionality |
501 | | * (i.e. OBMol::GetDimension()). |
502 | | * |
503 | | * @sa StereoFrom3D StereoFrom2D StereoFrom0D |
504 | | * @since version 2.3 |
505 | | */ |
506 | | OBAPI void PerceiveStereo(OBMol *mol, bool force = false); |
507 | | /** |
508 | | * Convert the 2D depiction of molecule @p mol to OBStereo objects. |
509 | | * This function makes use of the lower level functions |
510 | | * TetrahedralFrom2D(), CisTransFrom2D(), SquarePlanarFrom2D(), ... |
511 | | * |
512 | | * First, symmetry analysis taking stereochemistry into account is |
513 | | * performed iteratively (see OBGraphSym). Next the 2D coordinates, |
514 | | * OBBond::Wedge, OBBond::Hash, OBBond::WedgeOrHash and OBBond::CisOrTrans |
515 | | * are used to construct OBStereoBase derived objects to store the |
516 | | * stereochemistry. These objects will be added to @p mol. |
517 | | * |
518 | | * Unless perception is forced, this function does nothing if stereochemistry |
519 | | * has already been perceived (i.e. OBMol::HasChiralityPerceived()). Before |
520 | | * doing the actual perception, any data of the OBGenericDataType::StereoData |
521 | | * type will be deleted. |
522 | | * |
523 | | @verbatim |
524 | | Reference: |
525 | | [1] T. Cieplak, J.L. Wisniewski, A New Effective Algorithm for the |
526 | | Unambiguous Identification of the Stereochemical Characteristics of |
527 | | Compounds During Their Registration in Databases. Molecules 2000, 6, |
528 | | 915-926, http://www.mdpi.org/molecules/papers/61100915/61100915.htm |
529 | | @endverbatim |
530 | | * |
531 | | * @param mol The molecule containing 2D coordinates. |
532 | | * @param updown A map of OBStereo::BondDirection for cis/trans bonds |
533 | | * @param force Force to run the perception even if the results are cached. |
534 | | * |
535 | | * @sa StereoFrom3D StereoFrom0D PerceiveStereo |
536 | | * @since version 2.3 |
537 | | */ |
538 | | OBAPI void StereoFrom2D(OBMol *mol, |
539 | | std::map<OBBond*, enum OBStereo::BondDirection> *updown = nullptr, bool force = false); |
540 | | /** |
541 | | * Convert the 3D coordinates of molecule @p mol to OBStereo objects. This |
542 | | * function makes use of the lower level functions TetrahedralFrom3D(), |
543 | | * CisTransFrom3D(), SquarePlanarFrom3D(), ... |
544 | | * |
545 | | * Unless perception is forced, this function does nothing if stereochemistry |
546 | | * has already been perceived (i.e. OBMol::HasChiralityPerceived()). Before |
547 | | * doing the actual perception, any data of the OBGenericDataType::StereoData |
548 | | * type will be deleted. |
549 | | * |
550 | | * @param mol The molecule containing 3D coordinates. |
551 | | * @param force Force to run the perception even if the results are cached. |
552 | | * |
553 | | * @sa StereoFrom3D StereoFrom0D PerceiveStereo |
554 | | * @since version 2.3 |
555 | | */ |
556 | | OBAPI void StereoFrom3D(OBMol *mol, bool force = false); |
557 | | /** |
558 | | * Add missing OBStereo objects. Unlike StereoFrom3D() and StereoFrom2D(), this |
559 | | * method only adds objects for previously unidentified objects since we |
560 | | * don't want to loose any information. The Config::specified flag for the |
561 | | * newly added structs is always set to false. |
562 | | * |
563 | | * For example, a smiles is read which has two tetrahedral centers. Only one has |
564 | | * stereochemisrty specified using a '@' character. StereoFrom0D() will detect the |
565 | | * second tetrahedral atom and add an OBTetrahedralStereo object to the molecule. |
566 | | * |
567 | | * @param mol The molecule. |
568 | | * |
569 | | * @sa StereoFrom3D StereoFrom2D PerceiveStereo |
570 | | * @since version 2.3 |
571 | | */ |
572 | | OBAPI void StereoFrom0D(OBMol *mol); |
573 | | ///@} |
574 | | |
575 | | ///@name Low level functions |
576 | | ///@{ |
577 | | /** |
578 | | * Get a vector with all OBTetrahedralStereo objects for the molecule. This |
579 | | * function is used by StereoFrom3D() with the @p addToMol parameter is set |
580 | | * to true. |
581 | | * |
582 | | * The algorithm to convert the 3D coordinates to OBTetrahedralStereo object |
583 | | * uses the sign of the volume described by the 4 center atom neighbors. Given |
584 | | * 4 points \f$a\f$, \f$b\f$, \f$c\f$ and \f$d\f$, the signed volume \f$S_v\f$ |
585 | | * is defined as: |
586 | | * |
587 | | \f[ S_v = \left| \begin{array}{ccc} |
588 | | x_b - x_a & y_b - y_a & z_b - z_a \\ |
589 | | x_c - x_a & y_c - y_a & z_c - z_a \\ |
590 | | x_d - x_a & y_d - y_a & z_d - z_a |
591 | | \end{array} \right| \f] |
592 | | * |
593 | | * The sign of \f$S_v\f$ changes when any of the points cross the plane defined |
594 | | * by the other 3 points. To make this less abstract one could say that |
595 | | * a change of sign is equal to inverting the tetrahedral stereochemistry. |
596 | | * |
597 | | * In case there are only 3 neighbor atoms for the tetrahedral center, the |
598 | | * center atom itself is used as 4th point. This only changes the magnitude |
599 | | * and not the sign of \f$S_v\f$ because the center atom is still on the same |
600 | | * side of the plane. |
601 | | * |
602 | | * This function is also used for symmetry analysis to handle cases where |
603 | | * there are two atoms in the same symmetry class that don't have the same |
604 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
605 | | * false and the returned objects will need to be deleted explicitly. |
606 | | * |
607 | | * @param mol The molecule. |
608 | | * @param stereoUnits The stereogenic units. |
609 | | * @param addToMol If true, the OBTetrahedralStereo objects will be added |
610 | | * to the molecule using OBBase::SetData(). |
611 | | * |
612 | | * @sa StereoFrom3D FindStereogenicUnits |
613 | | * @since version 2.3 |
614 | | */ |
615 | | OBAPI std::vector<OBTetrahedralStereo*> TetrahedralFrom3D(OBMol *mol, |
616 | | const OBStereoUnitSet &stereoUnits, bool addToMol = true); |
617 | | /** |
618 | | * Get a vector with all OBTetrahedralStereo objects for the molecule. This |
619 | | * function is used by StereoFrom2D() with the @p addToMol parameter is set |
620 | | * to true. |
621 | | * |
622 | | * The algorithm to convert the 2D coordinates and bond properties |
623 | | * (i.e. OBBond::Wedge, OBBond::Hash, OBBond::WedgeOrHash and OBBond::CisOrTrans) |
624 | | * uses the sign of a triangle. Given 3 points \f$a\f$, \f$b\f$ and \f$c\f$, the |
625 | | * sign of the trianle \f$S_t\f$ is defined as: |
626 | | * |
627 | | \f[ S_t = (x_a - x_c) (y_b - y_c) - (y_a - y_c) (x_b - x_c) \f] |
628 | | * |
629 | | * This is equation 6 from on the referenced web page. The 3 points used |
630 | | * to calculate the triangle sign always remain in the same plane (i.e. z = 0). |
631 | | * The actual meaning of \f$S_t\f$ (i.e. assignment of OBStereo::Winding) depends |
632 | | * on the 4th atom. When the atom is in front of the plane, the sign should be |
633 | | * changed to have the same absolute meaning for an atom behind the plane and the |
634 | | * same triangle. It is important to note that none of the z coordinates is ever |
635 | | * changed, the molecule always stays 2D (unlike methods which set a pseudo-z |
636 | | * coordinate). |
637 | | * |
638 | | * @todo document bond property interpretation! |
639 | | * |
640 | | * This function is also used for symmetry analysis to handle cases where |
641 | | * there are two atoms in the same symmetry class that don't have the same |
642 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
643 | | * false and the returned objects will need to be deleted explicitly. |
644 | | * |
645 | | @verbatim |
646 | | Reference: |
647 | | [1] T. Cieplak, J.L. Wisniewski, A New Effective Algorithm for the |
648 | | Unambiguous Identification of the Stereochemical Characteristics of |
649 | | Compounds During Their Registration in Databases. Molecules 2000, 6, |
650 | | 915-926, http://www.mdpi.org/molecules/papers/61100915/61100915.htm |
651 | | @endverbatim |
652 | | * |
653 | | * @param mol The molecule. |
654 | | * @param stereoUnits The stereogenic units. |
655 | | * @param addToMol If true, the OBTetrahedralStereo objects will be added |
656 | | * to the molecule using OBBase::SetData(). |
657 | | * |
658 | | * @sa StereoFrom2D FindStereogenicUnits |
659 | | * @since version 2.3 |
660 | | */ |
661 | | OBAPI std::vector<OBTetrahedralStereo*> TetrahedralFrom2D(OBMol *mol, |
662 | | const OBStereoUnitSet &stereoUnits, bool addToMol = true); |
663 | | /** |
664 | | * Get a vector with all OBTetrahedralStereo objects for the molecule. This |
665 | | * function is used by StereoFrom0D() with the @p addToMol parameter is set |
666 | | * to true. There is no algorithm used here, all specified flags will be |
667 | | * set to false. |
668 | | * |
669 | | * This function is also used for symmetry analysis to handle cases where |
670 | | * there are two atoms in the same symmetry class that don't have the same |
671 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
672 | | * false and the returned objects will need to be deleted explicitly. |
673 | | * |
674 | | * @param mol The molecule. |
675 | | * @param stereoUnits The stereogenic units. |
676 | | * @param addToMol If true, the OBTetrahedralStereo objects will be added |
677 | | * to the molecule using OBBase::SetData(). |
678 | | * |
679 | | * @sa StereoFrom0D FindStereogenicUnits |
680 | | * @since version 2.3 |
681 | | */ |
682 | | OBAPI std::vector<OBTetrahedralStereo*> TetrahedralFrom0D(OBMol *mol, |
683 | | const OBStereoUnitSet &stereoUnits, bool addToMol = true); |
684 | | |
685 | | /** |
686 | | * Get a vector with all OBCisTransStereo objects for the molecule. This |
687 | | * function is used by StereoFrom3D() with the @p addToMol parameter is set |
688 | | * to true. |
689 | | * |
690 | | * The algorithm to convert the 3D coordinates to OBCisTransStereo objects |
691 | | * considers the signed distance between the attached atoms and the plane |
692 | | * through the double bond at right angles to the plane of the attached |
693 | | * atoms. Bonds on the same side (cis) will share the same sign for the |
694 | | * signed distance. |
695 | | * |
696 | | * Missing atom coordinates (OBStereo::ImplicitRef) and their bond |
697 | | * vectors will be computed if needed. |
698 | | * |
699 | | @verbatim |
700 | | 0 3 Get signed distance of 0 and 2 to the plane |
701 | | \ / that goes through the double bond and is at |
702 | | C==C right angles to the stereo bonds. |
703 | | / \ |
704 | | 1 2 If the two signed distances have the same sign |
705 | | then they are cis; if not, then trans. |
706 | | @endverbatim |
707 | | * |
708 | | * This function is also used for symmetry analysis to handle cases where |
709 | | * there are two atoms in the same symmetry class that don't have the same |
710 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
711 | | * false and the returned objects will need to be deleted explicitly. |
712 | | * |
713 | | * @param mol The molecule. |
714 | | * @param stereoUnits The stereogenic units. |
715 | | * @param addToMol If true, the OBCisTransStereo objects will be added |
716 | | * to the molecule using OBBase::SetData(). |
717 | | * |
718 | | * @sa StereoFrom3D FindStereogenicUnits |
719 | | * @since version 2.3 |
720 | | */ |
721 | | OBAPI std::vector<OBCisTransStereo*> CisTransFrom3D(OBMol *mol, |
722 | | const OBStereoUnitSet &stereoUnits, bool addToMol = true); |
723 | | /** |
724 | | * Get a vector with all OBCisTransStereo objects for the molecule. This |
725 | | * function is used by StereoFrom2D() with the @p addToMol parameter is set |
726 | | * to true. |
727 | | * |
728 | | * This function is also used for symmetry analysis to handle cases where |
729 | | * there are two atoms in the same symmetry class that don't have the same |
730 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
731 | | * false and the returned objects will need to be deleted explicitly. |
732 | | * |
733 | | * The algorithm for converting the 2D coordinates uses the same triangle |
734 | | * sign as TetrahedralFrom2D(). Depending on sign of 2 triangles, the right |
735 | | * OBStereo::Shape is selected. |
736 | | @verbatim |
737 | | 0 3 |
738 | | \ / 2 triangles: 0-1-b & 2-3-a |
739 | | a==b --> same sign: U |
740 | | / \ opposite sign: Z |
741 | | 1 2 |
742 | | @endverbatim |
743 | | * |
744 | | * @param mol The molecule. |
745 | | * @param stereoUnits The stereogenic units. |
746 | | * @param updown A map of OBStereo::BondDirection for cis/trans bonds |
747 | | * @param addToMol If true, the OBCisTransStereo objects will be added |
748 | | * to the molecule using OBBase::SetData(). |
749 | | * |
750 | | * @sa StereoFrom2D FindStereogenicUnits |
751 | | * @since version 2.3 |
752 | | */ |
753 | | OBAPI std::vector<OBCisTransStereo*> CisTransFrom2D(OBMol *mol, |
754 | | const OBStereoUnitSet &stereoUnits, |
755 | | const std::map<OBBond*, enum OBStereo::BondDirection> *updown = nullptr, bool addToMol = true); |
756 | | /** |
757 | | * Convert a molecule's OBTetrahedralStereo objects to a series of hash or |
758 | | * wedge bonds. Note that the molecule itself is not modified; the result |
759 | | * is returned in the maps @p updown and @p from, which indicate |
760 | | * the origin and direction of each hash or wedge bond. |
761 | | * |
762 | | * When converting, the following guidelines are followed when trying to |
763 | | * find the best candidate bond to set up/down for each OBTetrahedralStereo |
764 | | * object: |
765 | | * -# Should not already be set |
766 | | * -# Should not be connected to a 2nd tet center |
767 | | * (this is acceptable in theory as the wedge is only at one end, but |
768 | | * in practice it may cause confusion and thus we avoid it) |
769 | | * -# Preferably is not in a cycle |
770 | | * -# Preferably is a terminal H |
771 | | * |
772 | | * If no bond can be found that matches rules 1 and 2 (and in theory this is possible) |
773 | | * then an error message is logged and the function returns false. (If you find an |
774 | | * example where this occurs, please file a bug.) |
775 | | * |
776 | | * @param mol The molecule. |
777 | | * @param updown A map of OBStereo::BondDirection for each hash/wedge bond |
778 | | * @param from A map of OBStereo::Ref indicating the origin of each hash/wedge bond |
779 | | * @return True or False depending on whether the conversion was successful |
780 | | * @since version 2.3 |
781 | | */ |
782 | | OBAPI bool TetStereoToWedgeHash(OBMol &mol, |
783 | | std::map<OBBond*, enum OBStereo::BondDirection> &updown, |
784 | | std::map<OBBond*, OBStereo::Ref> &from); |
785 | | /** |
786 | | * Return a set of double bonds corresponding to the OBCisTransStereo objects |
787 | | * for which the stereochemistry is undefined. |
788 | | * |
789 | | * Note that this functions just iterates over the existing OBCisTransStereo |
790 | | * objects - it does not try to identify new ones. |
791 | | * |
792 | | * @param mol The molecule |
793 | | * @return A set of bonds with unspecified cis/trans stereochemistry |
794 | | * @since version 2.3 |
795 | | */ |
796 | | OBAPI std::set<OBBond*> GetUnspecifiedCisTrans(OBMol& mol); |
797 | | /** |
798 | | * Convert any reference to @p atomId in a stereo object to an OBStereo::ImplicitRef. |
799 | | * This function is called from OBMol::DeleteHydrogens() |
800 | | * (via OBMol::DeleteHydrogen()) to remove any explicit references to a |
801 | | * hydrogen atom that has been deleted. However, the code is not specific |
802 | | * to hydrogen atoms and could be used for other atoms. |
803 | | * |
804 | | * @param mol The molecule |
805 | | * @param atomId The Id of the atom to be converted to an OBStereo::ImplicitRef |
806 | | * @since version 2.3 |
807 | | */ |
808 | | OBAPI void StereoRefToImplicit(OBMol& mol, OBStereo::Ref atomId); |
809 | | /** |
810 | | * Convert any reference to an OBStereo::ImplicitRef attached to @p centerId |
811 | | * in a stereo object to an explicit reference to @p newId. |
812 | | * This function is called from OBMol::AddHydrogens() and |
813 | | * OBMol::AddHydrogen() to convert any implicit references to a |
814 | | * hydrogen atom that has just been added. However, the code is not specific |
815 | | * to hydrogen atoms and could be used for other atoms. |
816 | | * |
817 | | * @param mol The molecule |
818 | | * @param centerId The Id of the atom to which the new explicit atom is attached |
819 | | * @param newId The Id of the atom which was previously an OBStereo::ImplicitRef |
820 | | * @since version 2.4 |
821 | | */ |
822 | | OBAPI void ImplicitRefToStereo(OBMol& mol, OBStereo::Ref centerId, OBStereo::Ref newId); |
823 | | /** |
824 | | * Get a vector with all OBCisTransStereo objects for the molecule. This |
825 | | * function is used by StereoFrom0D() with the @p addToMol parameter is set |
826 | | * to true. There is no algorithm used here, all specified flags will be |
827 | | * set to false. |
828 | | * |
829 | | * This function is also used for symmetry analysis to handle cases where |
830 | | * there are two atoms in the same symmetry class that don't have the same |
831 | | * stereochemistry. In this situation, the @p addToMol parameter is set to |
832 | | * false and the returned objects will need to be deleted explicitly. |
833 | | * |
834 | | * @param mol The molecule. |
835 | | * @param stereoUnits The stereogenic units. |
836 | | * @param addToMol If true, the OBCisTransStereo objects will be added |
837 | | * to the molecule using OBBase::SetData(). |
838 | | * |
839 | | * @sa StereoFrom0D FindStereogenicUnits |
840 | | * @since version 2.3 |
841 | | */ |
842 | | OBAPI std::vector<OBCisTransStereo*> CisTransFrom0D(OBMol *mol, |
843 | | const OBStereoUnitSet &stereoUnits, |
844 | | bool addToMol = true); |
845 | | ///@} |
846 | | |
847 | | |
848 | | ///@name Stereogenic unit identification |
849 | | ///@{ |
850 | | /** |
851 | | * Find the stereogenic units in a molecule using a set of rules.<sup>1</sup> |
852 | | * |
853 | | * The potential stereocenters are identified first. A potential tetrahedral |
854 | | * stereogenic atom is any atom meeting the following criteria: |
855 | | * |
856 | | * - sp3 hybridization |
857 | | * - at least 3 "heavy" neighbors |
858 | | * |
859 | | * Nitrogen is treated as a special case since the barrier of inversion is |
860 | | * low in many cases making the atom non-stereogenic. Only bridge-head |
861 | | * nitrogen atoms (i.e. nitrogen has 3 neighbors in rings) will be |
862 | | * considered stereogenic. |
863 | | * |
864 | | * Potential stereogenic double bonds are identified using another set of |
865 | | * simple criteria: |
866 | | * |
867 | | * - must be a double bond |
868 | | * - must not be in a ring |
869 | | * - both begin and end atom should have at least one single bond |
870 | | * |
871 | | * True stereocenters (i.e. stereocenters with topologically different |
872 | | * ligands) are identified first. For tetrahedral stereocenters, true |
873 | | * stereocenters will have 4 different neighbor atom symmetry classes |
874 | | * and this can be expressed using T1234 to classify these stereocenters. |
875 | | * For stereogenic bonds, a similar classification C12 can be used but |
876 | | * both begin and end atom have their own classification and the bond |
877 | | * is only a true stereocenter if both atoms are C12. |
878 | | * |
879 | | * Para stereocenters are all stereocenters where there are at least two |
880 | | * equivalent neighbor atom symmetry classes. These are T1123, T1112, T1111 |
881 | | * and T1122 for tetrahedral stereocenters and C11 for double bonds. To |
882 | | * determine which of the remaining potential stereocenters really are |
883 | | * stereocenters, a set of rules is used.<sup>1</sup> |
884 | | * |
885 | | * Rule 1 is applied recusively: |
886 | | * |
887 | | * All rings are merged "mergedRings". A merged ring is simply a fragment consisting |
888 | | * of all atoms of a ring system (bridged, spiro, adjacent, ...). If two rings in the |
889 | | * SSSR set share an atom, they are merged. |
890 | | * |
891 | | * Each merged must at least have two para-stereocenters (or 1 true + 1 para) in order |
892 | | * for the para-stereocenter to be valid. This is repeated until no new stereocenters |
893 | | * are identified. |
894 | | * |
895 | | * rule 1a for double bonds: |
896 | | * - bond atom in ring has two identical symmetry classes for it's neighbor atoms (-> para) |
897 | | * - other bond atom: |
898 | | * - has two different symmetry classes for it's neighbours -> new stereocenter |
899 | | * - has two identical symmetry classes, but the ligand contains at least 1 true or para stereocenter -> new stereocenter |
900 | | * |
901 | | * rule 1b for tetracoord atoms: |
902 | | * - at least two neighbour symmetry classes are the same (-> para) |
903 | | * - other pair: |
904 | | * - has two different symmetry classes for it's neighbours -> new stereocenter |
905 | | * - has two identical symmetry classes, but the ligand contains at least 1 true or para stereocenter -> new stereocenter |
906 | | * |
907 | | * Rules 2 and 3 are applied sequential (i.e. only once). |
908 | | * |
909 | | * Rule 2a for tetracoordinate carbon: |
910 | | * - 1 or 2 pair identical ligands |
911 | | * - each ligand contains at least 1 true-stereocenter or 2 para-stereocenters (from rule 1) |
912 | | * |
913 | | * Rule 2b for tetracoordinate carbon: |
914 | | * - 3 or 4 identical ligands with at least |
915 | | * - 2 true-stereocenters |
916 | | * - 2 separate assemblies of para-stereocenters (from rule 1) |
917 | | * |
918 | | * Rule 3 for double bonds: |
919 | | * - 1 or 2 pair identical ligands (on begin and end atom) |
920 | | * - each pair contains at least 1 true-stereocenter or 2 para-stereocenters (from rule 1) |
921 | | * |
922 | | * |
923 | | * @verbatim |
924 | | Reference: |
925 | | [1] M. Razinger, K. Balasubramanian, M. Perdih, M. E. Munk, Stereoisomer |
926 | | Generation in Computer-Enhanced Structure Elucidation, J. Chem. Inf. |
927 | | Comput. Sci. 1993, 33, 812-825 |
928 | | @endverbatim |
929 | | */ |
930 | | OBAPI OBStereoUnitSet FindStereogenicUnits(OBMol *mol, |
931 | | const std::vector<unsigned int> &symClasses); |
932 | | /** |
933 | | * @brief Find the stereogenic units in a molecule making use of the automorphisms. |
934 | | * |
935 | | * The potential stereocenters are identified first. A potential tetrahedral |
936 | | * stereogenic atom is any atom meeting the following criteria: |
937 | | * |
938 | | * - sp3 hybridization |
939 | | * - at least 3 "heavy" neighbors |
940 | | * |
941 | | * Nitrogen is treated as a special case since the barrier of inversion is |
942 | | * low in many cases making the atom non-stereogenic. Only bridge-head |
943 | | * nitrogen atoms (i.e. nitrogen has 3 neighbors in rings) will be |
944 | | * considered stereogenic. |
945 | | * |
946 | | * Potential stereogenic double bonds are identified using another set of |
947 | | * simple criteria: |
948 | | * |
949 | | * - must be a double bond |
950 | | * - must not be in a ring |
951 | | * - both begin and end atom should have at least one single bond |
952 | | * |
953 | | * Once the potential stereocenters are found, the automorphisms are the key |
954 | | * to identifying real stereogenic units. Automorphisms can be seen as |
955 | | * permutations that permutate a graph back to the same graph. Such a |
956 | | * permutation can only exchange atoms with the same symmetry class and it |
957 | | * follows that the use of automorphisms takes symmetry into account. The |
958 | | * definitions below use a concept where the automorphisms cause inversions |
959 | | * of configuration to potential stereocenters. Such an inversion occurs |
960 | | * whenever an automorphism exchanges two equivalent (i.e. with the same |
961 | | * symmetry class) neighbor atoms attached to the potential stereogenic unit. |
962 | | * |
963 | | * @par Definition for tetrahedral stereocenters: |
964 | | * A potential stereocenter really is a stereocenter if there exists no automorphic |
965 | | * permutation causing an inversion of the configuration of only the potential |
966 | | * stereogenic unit under consideration. |
967 | | * If there exists at least one automorphic permutation causing an inversion of |
968 | | * the configuration, then the potential stereogenic center can be a stereogenic |
969 | | * center if the number of topologically equivalent neighbors (ligands) of the |
970 | | * potential stereogenic center is less than or equal to the number of different |
971 | | * configurations of these ligands.<sup>1</sup> |
972 | | * |
973 | | * The actual number of configurations needed for the ligands depends on the |
974 | | * classification (i.e. T1234, T1123, ...) of the stereo center. These classes |
975 | | * reflect the symmetry classes of the neighbor atoms of the center. |
976 | | * |
977 | | * - T1123: 1 true stereocenter OR 2 para stereocenters |
978 | | * - T1122: 1 true stereocenter OR 2 para stereocenters (for both) |
979 | | * - T1112: 2 true stereocenters OR 2 para stereocenter assemblies |
980 | | * - T1111: 2 true stereocenters OR 2 para stereocenter assemblies |
981 | | * |
982 | | * @par Definition for double bond stereocenters: |
983 | | * A potential stereogenic double bond really is a stereogenic bond if there |
984 | | * exists no automorphic permutation causing an inversion of the configuration |
985 | | * of only the potential stereogenic unit under consideration. The bond can still |
986 | | * be a stereogenic bond if there exists such an automorphism when the number of |
987 | | * configurations of the pair of topologically equivalent geminal ligands, which |
988 | | * are exchanged by the automorphism, is greater than or equal to two (i.e. the |
989 | | * number of topologically equivalent geminal ligands.<sup>1</sup> |
990 | | * |
991 | | * For stereogenic bonds, there is only one case but both begin and end atom |
992 | | * have to be checked. |
993 | | * |
994 | | * - C11: 1 true stereocenter OR 1 para stereocenter |
995 | | * |
996 | | * These criteria are analogous to the rules from the Razinger paper on |
997 | | * stereoisomer generation. Since the existence of stereocenters can depend |
998 | | * on the existence of other stereocenters (in the ligands), the stereocenters |
999 | | * are found by iterating until no new stereocenters are found. |
1000 | | * |
1001 | | * @verbatim |
1002 | | Reference: |
1003 | | [1] M. Perdih, M. Razinger, Stereochemistry and Sequence Rules: |
1004 | | A Proposal for Modification of Cahn-Ingold-Prelog System, |
1005 | | Tetrahedron: Asymmetry, 1994, Vol. 5, No. 5, 835-861 |
1006 | | @endverbatim |
1007 | | */ |
1008 | | OBAPI OBStereoUnitSet FindStereogenicUnits(OBMol *mol, |
1009 | | const std::vector<unsigned int> &symClasses, |
1010 | | const Automorphisms &automorphisms); |
1011 | | ///@} |
1012 | | |
1013 | | /** |
1014 | | * @page Stereochemistry |
1015 | | * @section overview Overview of classes |
1016 | | * |
1017 | | * There are many molecules which contain stereogenic elements. However, |
1018 | | * certain cases (i.e. tetrahedral, cis/trans) are more common than others |
1019 | | * (i.e. allene, biphenyl, octrahedral, ...). For the common stereogenic |
1020 | | * units, classes are provided. The inheritance of these classes resembles |
1021 | | * the way they are split into groups. |
1022 | | * |
1023 | | * - OBStereoBase |
1024 | | * - OBTetraNonPlanarStereo |
1025 | | * - OBTetrahedralStereo |
1026 | | * - OBExtendedTetrahedralStereo |
1027 | | * - OBTetraPlanarStereo |
1028 | | * - OBCisTransStereo |
1029 | | * - OBExtendedCisTransStereo |
1030 | | * - OBSquarePlanarStereo |
1031 | | * - OBAxialStereo |
1032 | | * - OBTrigonalBipyrimidalStereo |
1033 | | * - OBOctahedralStereo |
1034 | | * |
1035 | | * @image html tetranonplanar.png |
1036 | | * @image html tetraplanar.png |
1037 | | * |
1038 | | * All specific classes (i.e. OBTetrahedralStereo, ...) have embedded Config |
1039 | | * structs which define the actual stereochemistry. All these Config structs |
1040 | | * use OBStereo::Ref values to reference or uniquely identify atoms. Make sure |
1041 | | * to read about OBStereo::Ref and the related functions (in OBStereo). OBStereo |
1042 | | * is also a placeholder for various enums with predefined values for parameters |
1043 | | * etc. These enums are used throughout the different stereo classes but having |
1044 | | * these enums in a single location makes it easier to remember. When working |
1045 | | * with stereo classes, you normally don't need to use any of the parent classes |
1046 | | * directly. Only OBStereo and the specific class are needed. |
1047 | | * |
1048 | | * @section usage Basic usage |
1049 | | * |
1050 | | * The OBStereoFacade hides the complexity of working with stereochemistry. When |
1051 | | * using openbabel as a library, this is by far the easiest way to access |
1052 | | * stereochemistry information. |
1053 | | * The header for the specific OBStereo::Type type is all you need to include. |
1054 | | * These are: |
1055 | | * - @em openbabel/stereo/tetrahedral.h |
1056 | | * - @em openbabel/stereo/cistrans.h |
1057 | | * - @em openbabel/stereo/squareplanar.h |
1058 | | * |
1059 | | * All these headers also include @em openbabel/stereo/stereo.h providing |
1060 | | * declarations for OBStereo & OBStereoFacade. |
1061 | | * |
1062 | | @code |
1063 | | #include <iostream> |
1064 | | #include <openbabel/mol.h> |
1065 | | #include <openbabel/obconversion.h> |
1066 | | |
1067 | | #include <openbabel/stereo/tetrahedral.h> |
1068 | | |
1069 | | using namespace OpenBabel; |
1070 | | |
1071 | | int main() |
1072 | | { |
1073 | | OBMol mol; |
1074 | | OBConversion conv; |
1075 | | conv.SetInFormat("smi"); |
1076 | | conv.ReadString(&mol, "C[C@H](Cl)Br"); |
1077 | | |
1078 | | OBStereoFacade facade(&mol); |
1079 | | |
1080 | | FOR_ATOMS_OF_MOL(atom, mol) { |
1081 | | if (facade.HasTetrahedralStereo(atom->GetId())) |
1082 | | std::cout << facade.GetTetrahedralStereo(atom->GetId()) << std::endl; |
1083 | | } |
1084 | | } |
1085 | | @endcode |
1086 | | * |
1087 | | * All specific stereo classes and their embedded Config struct have an |
1088 | | * operator<< function which allows them to be used with std::ostream objects |
1089 | | * (e.g. std::cout, std::err, ...). These functions are often useful when |
1090 | | * debugging code. |
1091 | | * |
1092 | | * @section details Details on implementation |
1093 | | * |
1094 | | * The detection of stereogenic units start with symmetry analysis. However, a |
1095 | | * complete symmetry analysis also needs to take stereochemistry into account. |
1096 | | * In practice, this means stereochemistry will be found iteratively. At each |
1097 | | * iteration, the current atom symmetry classes are used to identify stereogenic |
1098 | | * units. The details about how the symmetry classes are used depends on the type |
1099 | | * (OBStereo::Type) of stereogenic unit. For tetrahedral centers, having 3 heavy |
1100 | | * atom neighbors with different symmetry classes or 4 neighbors with different |
1101 | | * symmetry classes means the atom is chiral. See FindStereogenicUnits() for |
1102 | | * details. |
1103 | | * |
1104 | | * After identifying the stereogenic units, Config structs with all the |
1105 | | * information on the spacial arrangement of the groups still have to be |
1106 | | * created. This involves interpreting various ways to represent |
1107 | | * stereochemisrty: |
1108 | | * |
1109 | | * - 3D coordinates: StereoFrom3D() |
1110 | | * - 2D coordinates: StereoFrom2D() |
1111 | | * - 0D coordinates: StereoFrom0D() |
1112 | | * |
1113 | | * Both StereoFrom3D() and StereoFrom2D() delete all existing stereochemistry objects |
1114 | | * before adding new ones. For molecules with 3D coordinates, it is evident that |
1115 | | * all information is specified by the coordinates itself. However, if a file format |
1116 | | * uses stereo parity flags, Config structs must be constructed using lower level |
1117 | | * functions and StereoFrom3D() should not be called. In these cases information |
1118 | | * could be lost by calling StereoFrom3D() after reading the file (the stereo flag might have |
1119 | | * indicated the stereochemistry was unspecified or the flag might not match the |
1120 | | * coordinates). In the case of 2D molecules, the coordinates together with bond |
1121 | | * properties (OBBond::Hash, OBBond::Wedge, OBBond::WedgeOrHash and |
1122 | | * OBBond::CisOrTrans) define the stereochemistry. Again, lower level functions |
1123 | | * can be used when stereo flags need to be used. |
1124 | | * |
1125 | | * StereoFrom0D() works slightly different than 3D/2D. Here, deleting the |
1126 | | * stereochemistry would always result in lost information. Instead StereoFrom0D() |
1127 | | * only adds new objects for stereogenic units which were previously not found. |
1128 | | * For example, a smiles is read which has two tetrahedral centers. Only one has |
1129 | | * stereochemistry specified using a '@' character. StereoFrom0D() will detect the |
1130 | | * second tetrahedral atom and add an OBTetrahedralStereo object to the molecule. |
1131 | | * The Config::specified flag for the newly added structs is always set to false. |
1132 | | * |
1133 | | * Assuming the format code has correctly set the molecule dimensions (OBMol::GetDimesions), |
1134 | | * PerceiveStereo() will automatically select the correct function to call. |
1135 | | * When StereoFrom3D(), StereoFrom2D() or StereoFrom0D() are not used, make sure to always |
1136 | | * set OBMol::HasChiralityPerceived() before returning from the format's ReadMolecule(). |
1137 | | * |
1138 | | * |
1139 | | * @section formats Guidelines for formats |
1140 | | * @subsection input Reading files |
1141 | | * |
1142 | | * - Read the section above |
1143 | | * - The MDL format (mdlformat.cpp) is a good example for 2D/3D formats with or |
1144 | | * without parity flags. |
1145 | | * - The SMILES format (smilesformat.cpp) is a good example for 0D formats. |
1146 | | * |
1147 | | * @subsection output Writing files |
1148 | | * |
1149 | | * For many file formats no additional code is needed. For example, if a 3D format |
1150 | | * doesn't require stereo parity flags, writing the coordinates is enough. For 2D |
1151 | | * file formats it will often suffice to write the coordinates and bond properties. |
1152 | | * If parity flags are needed, the OBStereoFacade class can be used to retrieve the |
1153 | | * objects for all types of stereochemistry supported by the file format. |
1154 | | * |
1155 | | * |
1156 | | * |
1157 | | * |
1158 | | * |
1159 | | * @since version 2.3 |
1160 | | */ |
1161 | | |
1162 | | ///@} addtogroup |
1163 | | } |
1164 | | |
1165 | | #endif |
1166 | | |
1167 | | //! \file stereo.h |
1168 | | //! \brief Process molecular stereochemistry information. |