RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
DepictUtils.h
Go to the documentation of this file.
1//
2// Copyright (C) 2003-2022 Greg Landrum and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10#include <RDGeneral/export.h>
11#ifndef RD_DEPICT_UTILS_H
12#define RD_DEPICT_UTILS_H
13
14// REVIEW: remove extra headers here
15#include <RDGeneral/types.h>
16#include <GraphMol/RDKitBase.h>
17#include <GraphMol/RWMol.h>
18#include <GraphMol/ROMol.h>
22#include <Geometry/point.h>
23#include <queue>
24
25namespace RDDepict {
26
31RDKIT_DEPICTOR_EXPORT extern unsigned int MAX_COLL_ITERS;
33RDKIT_DEPICTOR_EXPORT extern unsigned int NUM_BONDS_FLIPS;
34
35// Path angle expansion parameters
39
40typedef std::vector<const RDGeom::Point2D *> VECT_C_POINT;
41
42typedef std::pair<int, int> PAIR_I_I;
43typedef std::vector<PAIR_I_I> VECT_PII;
45 bool operator()(const PAIR_I_I &pd1, const PAIR_I_I &pd2) const {
46 return pd1.first > pd2.first;
47 }
48};
49
50typedef std::priority_queue<PAIR_I_I, VECT_PII, gtIIPair> PR_QUEUE;
51
52typedef std::pair<double, PAIR_I_I> PAIR_D_I_I;
53typedef std::list<PAIR_D_I_I> LIST_PAIR_DII;
54
55//! Some utility functions used in generating 2D coordinates
56
57//! Embed a ring as a convex polygon in 2D
58/*!
59 The process here is very straightforward:
60
61 We take the center of the ring to lie at the origin, so put the first
62 point at the origin and then sweep
63 anti-clockwise by an angle A = 360/n for the next point.
64
65 The length of the arm (l) we want to sweep is easy to compute given the
66 bond length (b) we want to use for each bond in the ring (for now
67 we will assume that this bond legnth is the same for all bonds in the ring:
68
69 l = b/sqrt(2*(1 - cos(A))
70
71 the above formula derives from the triangle formula, where side 'c' is given
72 in terms of sides 'a' and 'b' as:
73
74 c = a^2 + b^2 - 2.a.b.cos(A)
75
76 where A is the angle between a and b
77 */
79 const RDKit::INT_VECT &ring);
80
82 const RDGeom::Transform2D &trans);
83
84//! Find a point that bisects the angle at rcr
85/*!
86 The new point lies between nb1 and nb2. The line (rcr, newPt) bisects the
87 angle 'ang' at rcr
88*/
90 const RDGeom::Point2D &rcr, double ang, const RDGeom::Point2D &nb1,
91 const RDGeom::Point2D &nb2);
92
93//! Reflect a set of point through the line joining two point
94/*!
95 ARGUMENTS:
96 \param coordMap a map of <int, point2D> going from atom id to current
97 coordinates of the points that need to be reflected:
98 The coordinates are overwritten
99 \param loc1 the first point of the line that is to be used as a
100 mirror
101 \param loc2 the second point of the line to be used as a mirror
102 */
104 const RDGeom::Point2D &loc1,
105 const RDGeom::Point2D &loc2);
106
108 const RDGeom::Point2D &loc1,
109 const RDGeom::Point2D &loc2);
110
111//! Set the neighbors yet to added to aid such that the atoms with the most subs
112/// fall on opposite sides
113/*!
114 Ok this needs some explanation
115 - Let A, B, C, D be the substituent on the central atom X (given
116 by atom index aid)
117 - also let A be the atom that is already embedded
118 - Now we want the order in which the remaining neighbors B,C,D are
119 added to X such that the atoms with atom with largest number of
120 substituent fall on opposite sides of X so as to minimize atom
121 clashes later in the depiction
122
123 E.g. let say we have the following situation
124<pre>
125 B
126 | |
127 A--X--C
128 | |
129 --D--
130 |
131</pre>
132 In this case the number substituent of A, B, C, D are 3, 1, 1,
133 4 respectively so want to A and D to go opposite sides and so that
134 we draw
135<pre>
136 B
137 | | |
138 A--X--D--
139 | | |
140 C
141</pre>
142 And the correct ordering of the neighbors is B,D,C
143*/
145 const RDKit::INT_VECT &nbrs,
146 const RDKit::ROMol &mol);
147
148//! \brief From a given set of fused rings find the "core" rings, i.e. the rings
149//! that are left after iteratively removing rings that are fused with only one
150//! other ring by one or two atoms
151/*
152 \param fusedRings list of all the rings in the fused system
153 \param coreRingsIds this is where the IDs of the core rings are written
154 \param mol the molecule of interest
155
156 \return list of rings that represent the core
157*/
159 const RDKit::VECT_INT_VECT &fusedRings, RDKit::INT_VECT &coreRingsIds,
160 const RDKit::ROMol &mol);
161
162//! \brief From a given set of rings find the ring the largest common elements
163/// with other rings
164/*
165 Bit of a weird function - this is typically called once we have embedded some
166 of the rings in a fused system and we are looking for the ring that must be
167 embedded (or merged) next. The heuristic used here is to pick the rings with
168 the maximum number of atoms in common with the rings that are already
169 embedded.
170
171 \param doneRings a vector of ring IDs that have been embedded already
172 \param fusedRings list of all the rings in the fused system \param nextId
173 this is where the ID for the next ring is written
174
175 \return list of atom ids that are common
176*/
178 const RDKit::INT_VECT &doneRings, const RDKit::VECT_INT_VECT &fusedRings,
179 int &nextId);
180
181typedef std::pair<int, int> INT_PAIR;
182typedef std::vector<INT_PAIR> INT_PAIR_VECT;
183typedef INT_PAIR_VECT::const_iterator INT_PAIR_VECT_CI;
184
185typedef std::pair<double, INT_PAIR> DOUBLE_INT_PAIR;
186
187//! Sort a list of atoms by their CIP rank
188/*!
189 \param mol molecule of interest
190 \param commAtms atoms that need to be ranked
191 \param ascending sort to an ascending order or a descending order
192*/
193template <class T>
195 const T &commAtms,
196 bool ascending = true);
197
198//! computes a subangle for an atom of given hybridization and degree
199/*!
200 \param degree the degree of the atom (number of neighbors)
201 \param htype the atom's hybridization
202
203 \return the subangle (in radians)
204*/
205inline double computeSubAngle(unsigned int degree,
207 double angle = M_PI;
208 switch (htype) {
210 case RDKit::Atom::SP3:
211 if (degree == 4) {
212 angle = M_PI / 2;
213 } else {
214 angle = 2 * M_PI / 3;
215 }
216 break;
217 case RDKit::Atom::SP2:
218 angle = 2 * M_PI / 3;
219 break;
220 default:
221 angle = 2. * M_PI / degree;
222 }
223 return angle;
224}
225
226//! computes the rotation direction between two vectors
227/*!
228
229 Let:
230
231 v1 = loc1 - center
232
233 v2 = loc2 - center
234
235 If remaining angle(v1, v2) is < 180 and corss(v1, v2) > 0.0 then the rotation
236 dir is +1.0
237
238 else if remAngle(v1, v2) is > 180 and cross(v1, v2) < 0.0 then rotation dir is
239 -1.0
240
241 else if remAngle(v1, v2) is < 180 and cross(v1, v2) < 0.0 then rotation dir is
242 -1.0
243
244 finally if remAngle(v1, v2) is > 180 and cross(v1, v2) < 0.0 then rotation dir
245 is +1.0
246
247 \param center the common point
248 \param loc1 endpoint 1
249 \param loc2 endpoint 2
250 \param remAngle the remaining angle about center in radians
251
252 \return the rotation direction (1 or -1)
253*/
254inline int rotationDir(const RDGeom::Point2D &center,
255 const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2,
256 double remAngle) {
257 auto pt1 = loc1 - center;
258 auto pt2 = loc2 - center;
259 auto cross = pt1.x * pt2.y - pt1.y * pt2.x;
260 auto diffAngle = M_PI - remAngle;
261 cross *= diffAngle;
262 if (cross >= 0.0) {
263 return -1;
264 } else {
265 return 1;
266 }
267}
268
269//! computes and return the normal of a vector between two points
270/*!
271 \param center the common point
272 \param other the endpoint
273
274 \return the normal
275*/
277 const RDGeom::Point2D &other) {
278 auto res = other - center;
279 res.normalize();
280 std::swap(res.x, res.y);
281 res.x *= -1;
282 return res;
283}
284
285//! computes the rotation angle between two vectors
286/*!
287 \param center the common point
288 \param loc1 endpoint 1
289 \param loc2 endpoint 2
290
291 \return the angle (in radians)
292*/
293inline double computeAngle(const RDGeom::Point2D &center,
294 const RDGeom::Point2D &loc1,
295 const RDGeom::Point2D &loc2) {
296 auto v1 = loc1 - center;
297 auto v2 = loc2 - center;
298 return v1.angleTo(v2);
299}
300
301//! \brief pick the ring to embed first in a fused system
302/*!
303 \param mol the molecule of interest
304 \param fusedRings the collection of the molecule's fused rings
305
306 \return the index of the ring with the least number of substitutions
307*/
309 const RDKit::ROMol &mol, const RDKit::VECT_INT_VECT &fusedRings);
310
311//! \brief find the rotatable bonds on the shortest path between two atoms
312//! we will ignore ring atoms, and double bonds which are marked cis/trans
313/*!
314 <b>Note</b> that rotatable in this context doesn't connect to the
315 standard chemical definition of a rotatable bond; we're just talking
316 about bonds than can be flipped in order to clean up the depiction.
317
318 \param mol the molecule of interest
319 \param aid1 index of the first atom
320 \param aid2 index of the second atom
321
322 \return a set of the indices of the rotatable bonds
323*/
325 unsigned int aid1,
326 unsigned int aid2);
327
328//! \brief find all the rotatable bonds in a molecule
329//! we will ignore ring atoms, and double bonds which are marked cis/trans
330/*!
331 <b>Note</b> that rotatable in this context doesn't connect to the
332 standard chemical definition of a rotatable bond; we're just talking
333 about bonds than can be flipped in order to clean up the depiction.
334
335 \param mol the molecule of interest
336
337 \return a set of the indices of the rotatable bonds
338*/
340 const RDKit::ROMol &mol);
341
342//! \brief check if an atom is a spiro center (belongs to exactly 2 rings)
343/*!
344 \param aid index of the atom
345 \param mol the molecule of interest
346
347 \return true if the atom is a spiro center
348*/
350 const RDKit::ROMol *mol);
351
352//! \brief find spiro centers on the shortest path between two atoms
353/*!
354 \param mol the molecule of interest
355 \param aid1 index of the first atom
356 \param aid2 index of the second atom
357
358 \return a set of the indices of spiro centers
359*/
361 const RDKit::ROMol &mol, unsigned int aid1, unsigned int aid2);
362
363//! Get the ids of the atoms and bonds that are connected to aid
365 const RDKit::ROMol *mol,
366 RDKit::INT_VECT &aids,
367 RDKit::INT_VECT &bids);
368
369//! Find pairs of bonds that can be permuted at a non-ring degree 4 atom
370/*!
371 This function will return only those pairs that cannot be
372 permuted by flipping a rotatble bond
373
374 D
375 |
376 b3
377 |
378 A-b1-B-b2-C
379 |
380 b4
381 |
382 E
383 For example in the above situation on the pairs (b1, b3) and (b1, b4) will be
384 returned
385 // All other permutations can be achieved via a rotatable bond flip.
386
387 ARGUMENTS:
388 \param center - location of the central atom
389 \param nbrBids - a vector (of length 4) containing the ids of the bonds to
390 the neighbors
391 \param nbrLocs - locations of the neighbors
392*/
394 const RDGeom::Point2D &center, const RDKit::INT_VECT &nbrBids,
395 const VECT_C_POINT &nbrLocs);
396
397//! returns the rank of the atom for determining draw order
398inline int getAtomDepictRank(const RDKit::Atom *at) {
399 const int maxAtNum = 1000;
400 const int maxDeg = 100;
401 int anum = at->getAtomicNum();
402 anum = anum == 1 ? maxAtNum : anum; // favor non-hydrogen atoms
403 int deg = at->getDegree();
404 return maxDeg * anum + deg;
405}
406
408 const RDKit::ROMol &query);
410 RDKit::RWMol &templateMol);
412 const RDKit::RWMol &reducedQuery, const RDKit::RWMol &molHs,
413 std::vector<RDKit::MatchVectType> &matches);
415 RDKit::ROMol &mol, const RDGeom::Transform3D &trans);
416} // namespace RDDepict
417
418#endif
pulls in the core RDKit functionality
Defines the primary molecule class ROMol as well as associated typedefs.
Defines the editable molecule class RWMol.
void normalize() override
Definition point.h:365
double angleTo(const Point2D &other) const
Definition point.h:397
The class for representing atoms.
Definition Atom.h:75
int getAtomicNum() const
returns our atomic number
Definition Atom.h:146
HybridizationType
store hybridization
Definition Atom.h:93
@ UNSPECIFIED
hybridization that hasn't been specified
Definition Atom.h:94
unsigned int getDegree() const
RWMol is a molecule class that is intended to be edited.
Definition RWMol.h:32
#define RDKIT_DEPICTOR_EXPORT
Definition export.h:121
int getAtomDepictRank(const RDKit::Atom *at)
returns the rank of the atom for determining draw order
RDKIT_DEPICTOR_EXPORT unsigned int NUM_BONDS_FLIPS
RDKIT_DEPICTOR_EXPORT double COLLISION_THRES
RDKIT_DEPICTOR_EXPORT void reducedToFullMatches(const RDKit::RWMol &reducedQuery, const RDKit::RWMol &molHs, std::vector< RDKit::MatchVectType > &matches)
RDKIT_DEPICTOR_EXPORT RDGeom::INT_POINT2D_MAP embedRing(const RDKit::INT_VECT &ring)
Some utility functions used in generating 2D coordinates.
std::pair< int, int > PAIR_I_I
Definition DepictUtils.h:42
RDKIT_DEPICTOR_EXPORT bool isSpiroCenter(unsigned int aid, const RDKit::ROMol *mol)
check if an atom is a spiro center (belongs to exactly 2 rings)
RDKIT_DEPICTOR_EXPORT RDKit::VECT_INT_VECT findCoreRings(const RDKit::VECT_INT_VECT &fusedRings, RDKit::INT_VECT &coreRingsIds, const RDKit::ROMol &mol)
From a given set of fused rings find the "core" rings, i.e. the rings that are left after iteratively...
int rotationDir(const RDGeom::Point2D &center, const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2, double remAngle)
computes the rotation direction between two vectors
RDKIT_DEPICTOR_EXPORT bool invertWedgingIfMolHasFlipped(RDKit::ROMol &mol, const RDGeom::Transform3D &trans)
RDKIT_DEPICTOR_EXPORT std::unique_ptr< RDKit::RWMol > prepareTemplateForRGroups(RDKit::RWMol &templateMol)
std::pair< double, INT_PAIR > DOUBLE_INT_PAIR
RDKIT_DEPICTOR_EXPORT int pickFirstRingToEmbed(const RDKit::ROMol &mol, const RDKit::VECT_INT_VECT &fusedRings)
pick the ring to embed first in a fused system
RDKIT_DEPICTOR_EXPORT double ANGLE_OPEN
RDKIT_DEPICTOR_EXPORT double BOND_LEN
std::vector< const RDGeom::Point2D * > VECT_C_POINT
Definition DepictUtils.h:40
RDKIT_DEPICTOR_EXPORT RDKit::INT_VECT getRotatableBonds(const RDKit::ROMol &mol, unsigned int aid1, unsigned int aid2)
find the rotatable bonds on the shortest path between two atoms we will ignore ring atoms,...
RDKIT_DEPICTOR_EXPORT void getNbrAtomAndBondIds(unsigned int aid, const RDKit::ROMol *mol, RDKit::INT_VECT &aids, RDKit::INT_VECT &bids)
Get the ids of the atoms and bonds that are connected to aid.
RDKIT_DEPICTOR_EXPORT double ANGLE_EXPANSION_INCREMENT
std::priority_queue< PAIR_I_I, VECT_PII, gtIIPair > PR_QUEUE
Definition DepictUtils.h:50
std::list< PAIR_D_I_I > LIST_PAIR_DII
Definition DepictUtils.h:53
RDKIT_DEPICTOR_EXPORT double HETEROATOM_COLL_SCALE
RDKIT_DEPICTOR_EXPORT RDKit::INT_VECT setNbrOrder(unsigned int aid, const RDKit::INT_VECT &nbrs, const RDKit::ROMol &mol)
double computeSubAngle(unsigned int degree, RDKit::Atom::HybridizationType htype)
computes a subangle for an atom of given hybridization and degree
std::vector< PAIR_I_I > VECT_PII
Definition DepictUtils.h:43
std::vector< INT_PAIR > INT_PAIR_VECT
RDKIT_DEPICTOR_EXPORT void transformPoints(RDGeom::INT_POINT2D_MAP &nringCor, const RDGeom::Transform2D &trans)
RDKIT_DEPICTOR_EXPORT INT_PAIR_VECT findBondsPairsToPermuteDeg4(const RDGeom::Point2D &center, const RDKit::INT_VECT &nbrBids, const VECT_C_POINT &nbrLocs)
Find pairs of bonds that can be permuted at a non-ring degree 4 atom.
std::pair< double, PAIR_I_I > PAIR_D_I_I
Definition DepictUtils.h:52
double computeAngle(const RDGeom::Point2D &center, const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2)
computes the rotation angle between two vectors
RDKIT_DEPICTOR_EXPORT double BOND_THRES
RDKIT_DEPICTOR_EXPORT RDKit::INT_VECT getAllRotatableBonds(const RDKit::ROMol &mol)
find all the rotatable bonds in a molecule we will ignore ring atoms, and double bonds which are mark...
RDKIT_DEPICTOR_EXPORT RDKit::INT_VECT getSpiroCenters(const RDKit::ROMol &mol, unsigned int aid1, unsigned int aid2)
find spiro centers on the shortest path between two atoms
RDKIT_DEPICTOR_EXPORT RDGeom::Point2D reflectPoint(const RDGeom::Point2D &point, const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2)
RDKIT_DEPICTOR_EXPORT RDGeom::Point2D computeBisectPoint(const RDGeom::Point2D &rcr, double ang, const RDGeom::Point2D &nb1, const RDGeom::Point2D &nb2)
Find a point that bisects the angle at rcr.
RDKIT_DEPICTOR_EXPORT RDKit::INT_VECT findNextRingToEmbed(const RDKit::INT_VECT &doneRings, const RDKit::VECT_INT_VECT &fusedRings, int &nextId)
From a given set of rings find the ring the largest common elements with other rings.
RDGeom::Point2D computeNormal(const RDGeom::Point2D &center, const RDGeom::Point2D &other)
computes and return the normal of a vector between two points
RDKIT_DEPICTOR_EXPORT bool hasTerminalRGroupOrQueryHydrogen(const RDKit::ROMol &query)
RDKIT_DEPICTOR_EXPORT void reflectPoints(RDGeom::INT_POINT2D_MAP &coordMap, const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2)
Reflect a set of point through the line joining two point.
RDKIT_DEPICTOR_EXPORT unsigned int MAX_ANGLE_EXPANSION_ITERS
RDKIT_DEPICTOR_EXPORT unsigned int MAX_COLL_ITERS
INT_PAIR_VECT::const_iterator INT_PAIR_VECT_CI
RDKIT_DEPICTOR_EXPORT double MAX_ANGLE_EXPANSION
RDKIT_DEPICTOR_EXPORT T rankAtomsByRank(const RDKit::ROMol &mol, const T &commAtms, bool ascending=true)
Sort a list of atoms by their CIP rank.
std::pair< int, int > INT_PAIR
std::map< int, Point2D > INT_POINT2D_MAP
Definition point.h:566
std::vector< int > INT_VECT
Definition types.h:223
std::vector< INT_VECT > VECT_INT_VECT
Definition types.h:237
bool operator()(const PAIR_I_I &pd1, const PAIR_I_I &pd2) const
Definition DepictUtils.h:45