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