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
35typedef std::vector<const RDGeom::Point2D *> VECT_C_POINT;
36
37typedef std::pair<int, int> PAIR_I_I;
38typedef std::vector<PAIR_I_I> VECT_PII;
40 bool operator()(const PAIR_I_I &pd1, const PAIR_I_I &pd2) const {
41 return pd1.first > pd2.first;
42 }
43};
44
45typedef std::priority_queue<PAIR_I_I, VECT_PII, gtIIPair> PR_QUEUE;
46
47typedef std::pair<double, PAIR_I_I> PAIR_D_I_I;
48typedef std::list<PAIR_D_I_I> LIST_PAIR_DII;
49
50//! Some utility functions used in generating 2D coordinates
51
52//! Embed a ring as a convex polygon in 2D
53/*!
54 The process here is very straightforward:
55
56 We take the center of the ring to lie at the origin, so put the first
57 point at the origin and then sweep
58 anti-clockwise by an angle A = 360/n for the next point.
59
60 The length of the arm (l) we want to sweep is easy to compute given the
61 bond length (b) we want to use for each bond in the ring (for now
62 we will assume that this bond legnth is the same for all bonds in the ring:
63
64 l = b/sqrt(2*(1 - cos(A))
65
66 the above formula derives from the triangle formula, where side 'c' is given
67 in terms of sides 'a' and 'b' as:
68
69 c = a^2 + b^2 - 2.a.b.cos(A)
70
71 where A is the angle between a and b
72 */
74
76 const RDGeom::Transform2D &trans);
77
78//! Find a point that bisects the angle at rcr
79/*!
80 The new point lies between nb1 and nb2. The line (rcr, newPt) bisects the
81 angle 'ang' at rcr
82*/
84 const RDGeom::Point2D &rcr, double ang, const RDGeom::Point2D &nb1,
85 const RDGeom::Point2D &nb2);
86
87//! Reflect a set of point through the line joining two point
88/*!
89 ARGUMENTS:
90 \param coordMap a map of <int, point2D> going from atom id to current
91 coordinates of the points that need to be reflected:
92 The coordinates are overwritten
93 \param loc1 the first point of the line that is to be used as a
94 mirror
95 \param loc2 the second point of the line to be used as a mirror
96 */
98 const RDGeom::Point2D &loc1,
99 const RDGeom::Point2D &loc2);
100
102 const RDGeom::Point2D &loc1,
103 const RDGeom::Point2D &loc2);
104
105//! Set the neighbors yet to added to aid such that the atoms with the most subs
106/// fall on opposite sides
107/*!
108 Ok this needs some explanation
109 - Let A, B, C, D be the substituent on the central atom X (given
110 by atom index aid)
111 - also let A be the atom that is already embedded
112 - Now we want the order in which the remaining neighbors B,C,D are
113 added to X such that the atoms with atom with largest number of
114 substituent fall on opposite sides of X so as to minimize atom
115 clashes later in the depiction
116
117 E.g. let say we have the following situation
118<pre>
119 B
120 | |
121 A--X--C
122 | |
123 --D--
124 |
125</pre>
126 In this case the number substituent of A, B, C, D are 3, 1, 1,
127 4 respectively so want to A and D to go opposite sides and so that
128 we draw
129<pre>
130 B
131 | | |
132 A--X--D--
133 | | |
134 C
135</pre>
136 And the correct ordering of the neighbors is B,D,C
137*/
139 const RDKit::INT_VECT &nbrs,
140 const RDKit::ROMol &mol);
141
142//! \brief From a given set of rings find the ring the largest common elements
143/// with other rings
144/*
145 Bit of a weird function - this is typically called once we have embedded some
146 of the rings in a fused system and we are looking for the ring that must be
147 embedded (or merged) next. The heuristic used here is to pick the rings with
148 the maximum number of atoms in common with the rings that are already
149 embedded.
150
151 \param doneRings a vector of ring IDs that have been embedded already
152 \param fusedRings list of all the rings in the fused system \param nextId
153 this is where the ID for the next ring is written
154
155 \return list of atom ids that are common
156*/
158 const RDKit::INT_VECT &doneRings, const RDKit::VECT_INT_VECT &fusedRings,
159 int &nextId);
160
161typedef std::pair<int, int> INT_PAIR;
162typedef std::vector<INT_PAIR> INT_PAIR_VECT;
163typedef INT_PAIR_VECT::const_iterator INT_PAIR_VECT_CI;
164
165typedef std::pair<double, INT_PAIR> DOUBLE_INT_PAIR;
166
167//! Sort a list of atoms by their CIP rank
168/*!
169 \param mol molecule of interest
170 \param commAtms atoms that need to be ranked
171 \param ascending sort to an ascending order or a descending order
172*/
173template <class T>
175 const T &commAtms,
176 bool ascending = true);
177
178//! computes a subangle for an atom of given hybridization and degree
179/*!
180 \param degree the degree of the atom (number of neighbors)
181 \param htype the atom's hybridization
182
183 \return the subangle (in radians)
184*/
185inline double computeSubAngle(unsigned int degree,
187 double angle = M_PI;
188 switch (htype) {
190 case RDKit::Atom::SP3:
191 if (degree == 4) {
192 angle = M_PI / 2;
193 } else {
194 angle = 2 * M_PI / 3;
195 }
196 break;
197 case RDKit::Atom::SP2:
198 angle = 2 * M_PI / 3;
199 break;
200 default:
201 angle = 2. * M_PI / degree;
202 }
203 return angle;
204}
205
206//! computes the rotation direction between two vectors
207/*!
208
209 Let:
210
211 v1 = loc1 - center
212
213 v2 = loc2 - center
214
215 If remaining angle(v1, v2) is < 180 and corss(v1, v2) > 0.0 then the rotation
216 dir is +1.0
217
218 else if remAngle(v1, v2) is > 180 and cross(v1, v2) < 0.0 then rotation dir is
219 -1.0
220
221 else if remAngle(v1, v2) is < 180 and cross(v1, v2) < 0.0 then rotation dir is
222 -1.0
223
224 finally if remAngle(v1, v2) is > 180 and cross(v1, v2) < 0.0 then rotation dir
225 is +1.0
226
227 \param center the common point
228 \param loc1 endpoint 1
229 \param loc2 endpoint 2
230 \param remAngle the remaining angle about center in radians
231
232 \return the rotation direction (1 or -1)
233*/
234inline int rotationDir(const RDGeom::Point2D &center,
235 const RDGeom::Point2D &loc1, const RDGeom::Point2D &loc2,
236 double remAngle) {
237 auto pt1 = loc1 - center;
238 auto pt2 = loc2 - center;
239 auto cross = pt1.x * pt2.y - pt1.y * pt2.x;
240 auto diffAngle = M_PI - remAngle;
241 cross *= diffAngle;
242 if (cross >= 0.0) {
243 return -1;
244 } else {
245 return 1;
246 }
247}
248
249//! computes and return the normal of a vector between two points
250/*!
251 \param center the common point
252 \param other the endpoint
253
254 \return the normal
255*/
257 const RDGeom::Point2D &other) {
258 auto res = other - center;
259 res.normalize();
260 std::swap(res.x, res.y);
261 res.x *= -1;
262 return res;
263}
264
265//! computes the rotation angle between two vectors
266/*!
267 \param center the common point
268 \param loc1 endpoint 1
269 \param loc2 endpoint 2
270
271 \return the angle (in radians)
272*/
273inline double computeAngle(const RDGeom::Point2D &center,
274 const RDGeom::Point2D &loc1,
275 const RDGeom::Point2D &loc2) {
276 auto v1 = loc1 - center;
277 auto v2 = loc2 - center;
278 return v1.angleTo(v2);
279}
280
281//! \brief pick the ring to embed first in a fused system
282/*!
283 \param mol the molecule of interest
284 \param fusedRings the collection of the molecule's fused rings
285
286 \return the index of the ring with the least number of substitutions
287*/
289 const RDKit::ROMol &mol, const RDKit::VECT_INT_VECT &fusedRings);
290
291//! \brief find the rotatable bonds on the shortest path between two atoms
292//! we will ignore ring atoms, and double bonds which are marked cis/trans
293/*!
294 <b>Note</b> that rotatable in this context doesn't connect to the
295 standard chemical definition of a rotatable bond; we're just talking
296 about bonds than can be flipped in order to clean up the depiction.
297
298 \param mol the molecule of interest
299 \param aid1 index of the first atom
300 \param aid2 index of the second atom
301
302 \return a set of the indices of the rotatable bonds
303*/
305 unsigned int aid1,
306 unsigned int aid2);
307
308//! \brief find all the rotatable bonds in a molecule
309//! we will ignore ring atoms, and double bonds which are marked cis/trans
310/*!
311 <b>Note</b> that rotatable in this context doesn't connect to the
312 standard chemical definition of a rotatable bond; we're just talking
313 about bonds than can be flipped in order to clean up the depiction.
314
315 \param mol the molecule of interest
316
317 \return a set of the indices of the rotatable bonds
318*/
320 const RDKit::ROMol &mol);
321
322//! Get the ids of the atoms and bonds that are connected to aid
324 const RDKit::ROMol *mol,
325 RDKit::INT_VECT &aids,
326 RDKit::INT_VECT &bids);
327
328//! Find pairs of bonds that can be permuted at a non-ring degree 4 atom
329/*!
330 This function will return only those pairs that cannot be
331 permuted by flipping a rotatble bond
332
333 D
334 |
335 b3
336 |
337 A-b1-B-b2-C
338 |
339 b4
340 |
341 E
342 For example in the above situation on the pairs (b1, b3) and (b1, b4) will be
343 returned
344 All other permutations can be achieved via a rotatable bond flip.
345
346 ARGUMENTS:
347 \param center - location of the central atom
348 \param nbrBids - a vector (of length 4) containing the ids of the bonds to
349 the neighbors
350 \param nbrLocs - locations of the neighbors
351*/
353 const RDGeom::Point2D &center, const RDKit::INT_VECT &nbrBids,
354 const VECT_C_POINT &nbrLocs);
355
356//! returns the rank of the atom for determining draw order
357inline int getAtomDepictRank(const RDKit::Atom *at) {
358 const int maxAtNum = 1000;
359 const int maxDeg = 100;
360 int anum = at->getAtomicNum();
361 anum = anum == 1 ? maxAtNum : anum; // favor non-hydrogen atoms
362 int deg = at->getDegree();
363 return maxDeg * anum + deg;
364}
365
368 RDKit::RWMol &templateMol);
370 const RDKit::RWMol &reducedQuery, const RDKit::RWMol &molHs,
371 std::vector<RDKit::MatchVectType> &matches);
373 RDKit::ROMol &mol, const RDGeom::Transform3D &trans);
374} // namespace RDDepict
375
376#endif
#define M_PI
Definition MMFF/Params.h:27
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:346
double angleTo(const Point2D &other) const
Definition point.h:374
The class for representing atoms.
Definition Atom.h:75
HybridizationType
store hybridization
Definition Atom.h:86
@ UNSPECIFIED
hybridization that hasn't been specified
Definition Atom.h:87
int getAtomicNum() const
returns our atomic number
Definition Atom.h:134
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:89
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:37
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:35
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.
std::priority_queue< PAIR_I_I, VECT_PII, gtIIPair > PR_QUEUE
Definition DepictUtils.h:45
std::list< PAIR_D_I_I > LIST_PAIR_DII
Definition DepictUtils.h:48
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:38
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:47
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 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_COLL_ITERS
INT_PAIR_VECT::const_iterator INT_PAIR_VECT_CI
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:550
std::vector< int > INT_VECT
Definition types.h:284
std::vector< INT_VECT > VECT_INT_VECT
Definition types.h:298
bool operator()(const PAIR_I_I &pd1, const PAIR_I_I &pd2) const
Definition DepictUtils.h:40