/src/rdkit/Code/GraphMol/new_canon.h
Line | Count | Source |
1 | | // |
2 | | // Copyright (C) 2014 Greg Landrum |
3 | | // Adapted from pseudo-code from Roger Sayle |
4 | | // |
5 | | // @@ All Rights Reserved @@ |
6 | | // This file is part of the RDKit. |
7 | | // The contents are covered by the terms of the BSD license |
8 | | // which is included in the file license.txt, found at the root |
9 | | // of the RDKit source tree. |
10 | | // |
11 | | |
12 | | #ifndef RD_NEW_CANON_H |
13 | | #define RD_NEW_CANON_H |
14 | | |
15 | | #include <RDGeneral/export.h> |
16 | | #include <RDGeneral/hanoiSort.h> |
17 | | #include <GraphMol/ROMol.h> |
18 | | #include <GraphMol/RingInfo.h> |
19 | | #include <GraphMol/StereoGroup.h> |
20 | | #include <RDGeneral/BoostStartInclude.h> |
21 | | #include <cstdint> |
22 | | #include <boost/dynamic_bitset.hpp> |
23 | | #include <boost/container/small_vector.hpp> |
24 | | #include <RDGeneral/BoostEndInclude.h> |
25 | | #include <cstring> |
26 | | #include <cassert> |
27 | | #include <compare> |
28 | | #include <cstring> |
29 | | #include <span> |
30 | | #include <vector> |
31 | | |
32 | | // #define VERBOSE_CANON 1 |
33 | | |
34 | | namespace RDKit { |
35 | | namespace Canon { |
36 | | struct canon_atom; |
37 | | |
38 | | // Complete atom comparison key used after the current symmetry class. |
39 | | struct AtomCompareCode { |
40 | | int atomMapNumber{0}; |
41 | | unsigned int degree{0}; |
42 | | std::uint64_t primary{0}; |
43 | | std::uint64_t secondary{0}; |
44 | | |
45 | | // The defaulted comparison orders atom map, degree, primary, then secondary. |
46 | 0 | auto operator<=>(const AtomCompareCode &) const = default; |
47 | | }; |
48 | | |
49 | | struct RDKIT_GRAPHMOL_EXPORT bondholder { |
50 | | Bond::BondType bondType{Bond::BondType::UNSPECIFIED}; |
51 | | unsigned int bondStereo{ |
52 | | static_cast<unsigned int>(Bond::BondStereo::STEREONONE)}; |
53 | | unsigned int nbrSymClass{0}; |
54 | | unsigned int nbrIdx{0}; |
55 | | Bond::BondStereo stype{Bond::BondStereo::STEREONONE}; |
56 | | const canon_atom *controllingAtoms[4]{nullptr, nullptr, nullptr, nullptr}; |
57 | | const std::string *p_symbol{ |
58 | | nullptr}; // if provided, this is used to order bonds |
59 | | unsigned int bondIdx{0}; |
60 | | |
61 | 0 | bondholder() {}; |
62 | | bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, |
63 | | unsigned int nsc, unsigned int bidx) |
64 | 1.85M | : bondType(bt), |
65 | 1.85M | bondStereo(static_cast<unsigned int>(bs)), |
66 | 1.85M | nbrSymClass(nsc), |
67 | 1.85M | nbrIdx(ni), |
68 | 1.85M | bondIdx(bidx) {} |
69 | | bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, |
70 | | unsigned int nsc, unsigned int bidx) |
71 | 0 | : bondType(bt), |
72 | 0 | bondStereo(bs), |
73 | 0 | nbrSymClass(nsc), |
74 | 0 | nbrIdx(ni), |
75 | 0 | bondIdx(bidx) {} |
76 | | |
77 | | int compareStereo(const bondholder &o) const; |
78 | | |
79 | 0 | bool operator<(const bondholder &o) const { return compare(*this, o) < 0; } |
80 | 27.4M | static bool greater(const bondholder &lhs, const bondholder &rhs) { |
81 | 27.4M | return compare(lhs, rhs) > 0; |
82 | 27.4M | } |
83 | | |
84 | | static int compare(const bondholder &x, const bondholder &y, |
85 | 53.1M | unsigned int div = 1) { |
86 | 53.1M | if (x.p_symbol && y.p_symbol) { |
87 | 0 | auto symbolCompare = x.p_symbol->compare(*y.p_symbol); |
88 | 0 | if (symbolCompare != 0) { |
89 | 0 | return symbolCompare; |
90 | 0 | } |
91 | 0 | } |
92 | 53.1M | if (x.bondType < y.bondType) { |
93 | 1.58M | return -1; |
94 | 51.5M | } else if (x.bondType > y.bondType) { |
95 | 142k | return 1; |
96 | 142k | } |
97 | 51.3M | if (x.bondStereo < y.bondStereo) { |
98 | 3.63k | return -1; |
99 | 51.3M | } else if (x.bondStereo > y.bondStereo) { |
100 | 1.86k | return 1; |
101 | 1.86k | } |
102 | 51.3M | int scdiv; |
103 | 51.3M | if (div != 1) { |
104 | 0 | scdiv = x.nbrSymClass / div - y.nbrSymClass / div; |
105 | 51.3M | } else { |
106 | 51.3M | scdiv = x.nbrSymClass - y.nbrSymClass; |
107 | 51.3M | } |
108 | 51.3M | if (scdiv) { |
109 | 13.1M | return scdiv; |
110 | 13.1M | } |
111 | 38.2M | if (x.bondStereo && y.bondStereo) { |
112 | 619 | auto cs = x.compareStereo(y); |
113 | 619 | if (cs) { |
114 | 0 | return cs; |
115 | 0 | } |
116 | 619 | } |
117 | 38.2M | return 0; |
118 | 38.2M | } |
119 | | }; |
120 | | using BondholderVector = boost::container::small_vector<bondholder, 4>; |
121 | | struct RDKIT_GRAPHMOL_EXPORT canon_atom { |
122 | | const Atom *atom{nullptr}; |
123 | | int index{-1}; |
124 | | unsigned int degree{0}; |
125 | | unsigned int totalNumHs{0}; |
126 | | bool hasRingNbr{false}; |
127 | | bool isRingStereoAtom{false}; |
128 | | unsigned int whichStereoGroup{0}; |
129 | | StereoGroupType typeOfStereoGroup{StereoGroupType::STEREO_ABSOLUTE}; |
130 | | std::span<int> nbrIds; |
131 | | const std::string *p_symbol{ |
132 | | nullptr}; // if provided, this is used to order atoms |
133 | | std::vector<int> neighborNum; |
134 | | std::vector<int> revistedNeighbors; |
135 | | BondholderVector bonds; |
136 | | }; |
137 | | |
138 | | RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborIndex( |
139 | | canon_atom *atoms, std::vector<bondholder> &nbrs); |
140 | | RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborIndex(canon_atom *atoms, |
141 | | BondholderVector &nbrs); |
142 | | |
143 | | RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborNumSwaps( |
144 | | canon_atom *atoms, std::vector<bondholder> &nbrs, unsigned int atomIdx, |
145 | | std::vector<std::pair<unsigned int, unsigned int>> &result); |
146 | | RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborNumSwaps( |
147 | | canon_atom *atoms, BondholderVector &nbrs, unsigned int atomIdx, |
148 | | std::vector<std::pair<unsigned int, unsigned int>> &result); |
149 | | |
150 | | /* |
151 | | * Different types of atom compare functions: |
152 | | * |
153 | | * - SpecialChiralityAtomCompareFunctor: Allows canonizing molecules exhibiting |
154 | | *dependent chirality |
155 | | * - SpecialSymmetryAtomCompareFunctor: Very specialized, allows canonizing |
156 | | *highly symmetrical graphs/molecules |
157 | | * - AtomCompareFunctor: Basic atom compare function which also allows to |
158 | | *include neighbors within the ranking |
159 | | */ |
160 | | |
161 | | class RDKIT_GRAPHMOL_EXPORT SpecialChiralityAtomCompareFunctor { |
162 | | public: |
163 | | Canon::canon_atom *dp_atoms{nullptr}; |
164 | | const ROMol *dp_mol{nullptr}; |
165 | | const boost::dynamic_bitset<> *dp_atomsInPlay{nullptr}, |
166 | | *dp_bondsInPlay{nullptr}; |
167 | | |
168 | 0 | SpecialChiralityAtomCompareFunctor() {} |
169 | | SpecialChiralityAtomCompareFunctor( |
170 | | Canon::canon_atom *atoms, const ROMol &m, |
171 | | const boost::dynamic_bitset<> *atomsInPlay = nullptr, |
172 | | const boost::dynamic_bitset<> *bondsInPlay = nullptr) |
173 | 2.02k | : dp_atoms(atoms), |
174 | 2.02k | dp_mol(&m), |
175 | 2.02k | dp_atomsInPlay(atomsInPlay), |
176 | 2.02k | dp_bondsInPlay(bondsInPlay) {} |
177 | 3.25M | int operator()(int i, int j) const { |
178 | 3.25M | PRECONDITION(dp_atoms, "no atoms"); |
179 | 3.25M | PRECONDITION(dp_mol, "no molecule"); |
180 | 3.25M | PRECONDITION(i != j, "bad call"); |
181 | 3.25M | if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) { |
182 | 0 | return 0; |
183 | 0 | } |
184 | | |
185 | 3.25M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) { |
186 | 3.25M | updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds); |
187 | 3.25M | } |
188 | 3.25M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) { |
189 | 3.25M | updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds); |
190 | 3.25M | } |
191 | 3.25M | for (unsigned int ii = 0; |
192 | 4.65M | ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) { |
193 | 1.39M | int cmp = |
194 | 1.39M | bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]); |
195 | 1.39M | if (cmp) { |
196 | 58 | return cmp; |
197 | 58 | } |
198 | 1.39M | } |
199 | | |
200 | 3.25M | std::vector<std::pair<unsigned int, unsigned int>> swapsi; |
201 | 3.25M | std::vector<std::pair<unsigned int, unsigned int>> swapsj; |
202 | 3.25M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) { |
203 | 3.25M | updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[i].bonds, i, swapsi); |
204 | 3.25M | } |
205 | 3.25M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) { |
206 | 3.25M | updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[j].bonds, j, swapsj); |
207 | 3.25M | } |
208 | | |
209 | 4.64M | for (unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) { |
210 | 1.39M | int cmp = swapsi[ii].second - swapsj[ii].second; |
211 | | |
212 | 1.39M | if (cmp) { |
213 | 364 | return cmp; |
214 | 364 | } |
215 | 1.39M | } |
216 | | |
217 | 3.25M | return 0; |
218 | 3.25M | } |
219 | | }; |
220 | | |
221 | | class RDKIT_GRAPHMOL_EXPORT SpecialSymmetryAtomCompareFunctor { |
222 | | public: |
223 | | Canon::canon_atom *dp_atoms{nullptr}; |
224 | | const ROMol *dp_mol{nullptr}; |
225 | | const boost::dynamic_bitset<> *dp_atomsInPlay{nullptr}, |
226 | | *dp_bondsInPlay{nullptr}; |
227 | | |
228 | 0 | SpecialSymmetryAtomCompareFunctor() {} |
229 | | SpecialSymmetryAtomCompareFunctor( |
230 | | Canon::canon_atom *atoms, const ROMol &m, |
231 | | const boost::dynamic_bitset<> *atomsInPlay = nullptr, |
232 | | const boost::dynamic_bitset<> *bondsInPlay = nullptr) |
233 | 88 | : dp_atoms(atoms), |
234 | 88 | dp_mol(&m), |
235 | 88 | dp_atomsInPlay(atomsInPlay), |
236 | 88 | dp_bondsInPlay(bondsInPlay) {} |
237 | 200k | int operator()(int i, int j) const { |
238 | 200k | PRECONDITION(dp_atoms, "no atoms"); |
239 | 200k | PRECONDITION(dp_mol, "no molecule"); |
240 | 200k | PRECONDITION(i != j, "bad call"); |
241 | 200k | if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) { |
242 | 0 | return 0; |
243 | 0 | } |
244 | | |
245 | 200k | if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) { |
246 | 693 | return -1; |
247 | 200k | } else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) { |
248 | 1.01k | return 1; |
249 | 1.01k | } |
250 | | |
251 | 199k | if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) { |
252 | 43 | return -1; |
253 | 199k | } else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) { |
254 | 80 | return 1; |
255 | 80 | } |
256 | | |
257 | 199k | if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) { |
258 | 199k | updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds); |
259 | 199k | } |
260 | 199k | if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) { |
261 | 199k | updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds); |
262 | 199k | } |
263 | 199k | for (unsigned int ii = 0; |
264 | 420k | ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) { |
265 | 221k | int cmp = |
266 | 221k | bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]); |
267 | 221k | if (cmp) { |
268 | 28 | return cmp; |
269 | 28 | } |
270 | 221k | } |
271 | | |
272 | 199k | if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) { |
273 | 0 | return -1; |
274 | 199k | } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) { |
275 | 0 | return 1; |
276 | 0 | } |
277 | 199k | return 0; |
278 | 199k | } |
279 | | }; |
280 | | |
281 | | namespace { |
282 | | unsigned int getChiralRank(const ROMol *dp_mol, canon_atom *dp_atoms, |
283 | 112k | unsigned int i) { |
284 | 112k | unsigned int res = 0; |
285 | 112k | std::vector<unsigned int> perm; |
286 | 112k | perm.reserve(dp_atoms[i].atom->getDegree()); |
287 | 330k | for (const auto nbr : dp_mol->atomNeighbors(dp_atoms[i].atom)) { |
288 | 330k | auto rnk = dp_atoms[nbr->getIdx()].index; |
289 | | // make sure we don't have duplicate ranks |
290 | 330k | if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) { |
291 | 16.5k | break; |
292 | 313k | } else { |
293 | 313k | perm.push_back(rnk); |
294 | 313k | } |
295 | 330k | } |
296 | 112k | if (perm.size() == dp_atoms[i].atom->getDegree()) { |
297 | 95.8k | auto ctag = dp_atoms[i].atom->getChiralTag(); |
298 | 95.8k | if (ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW || |
299 | 95.8k | ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CCW) { |
300 | 95.8k | auto sortedPerm = perm; |
301 | 95.8k | std::sort(sortedPerm.begin(), sortedPerm.end()); |
302 | 95.8k | auto nswaps = countSwapsToInterconvert(perm, sortedPerm); |
303 | 95.8k | res = ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ? 2 : 1; |
304 | 95.8k | if (nswaps % 2) { |
305 | 46.0k | res = res == 2 ? 1 : 2; |
306 | 46.0k | } |
307 | 95.8k | } |
308 | 95.8k | } |
309 | 112k | return res; |
310 | 112k | } Unexecuted instantiation: Chirality.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) new_canon.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) Line | Count | Source | 283 | 112k | unsigned int i) { | 284 | 112k | unsigned int res = 0; | 285 | 112k | std::vector<unsigned int> perm; | 286 | 112k | perm.reserve(dp_atoms[i].atom->getDegree()); | 287 | 330k | for (const auto nbr : dp_mol->atomNeighbors(dp_atoms[i].atom)) { | 288 | 330k | auto rnk = dp_atoms[nbr->getIdx()].index; | 289 | | // make sure we don't have duplicate ranks | 290 | 330k | if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) { | 291 | 16.5k | break; | 292 | 313k | } else { | 293 | 313k | perm.push_back(rnk); | 294 | 313k | } | 295 | 330k | } | 296 | 112k | if (perm.size() == dp_atoms[i].atom->getDegree()) { | 297 | 95.8k | auto ctag = dp_atoms[i].atom->getChiralTag(); | 298 | 95.8k | if (ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW || | 299 | 95.8k | ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CCW) { | 300 | 95.8k | auto sortedPerm = perm; | 301 | 95.8k | std::sort(sortedPerm.begin(), sortedPerm.end()); | 302 | 95.8k | auto nswaps = countSwapsToInterconvert(perm, sortedPerm); | 303 | 95.8k | res = ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ? 2 : 1; | 304 | 95.8k | if (nswaps % 2) { | 305 | 46.0k | res = res == 2 ? 1 : 2; | 306 | 46.0k | } | 307 | 95.8k | } | 308 | 95.8k | } | 309 | 112k | return res; | 310 | 112k | } |
Unexecuted instantiation: FindStereo.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) Unexecuted instantiation: MolOps.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) Unexecuted instantiation: Kekulize.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) Unexecuted instantiation: Canon.cpp:RDKit::Canon::(anonymous namespace)::getChiralRank(RDKit::ROMol const*, RDKit::Canon::canon_atom*, unsigned int) |
311 | | } // namespace |
312 | | class RDKIT_GRAPHMOL_EXPORT AtomCompareFunctor { |
313 | 30.9M | unsigned int getAtomRingNbrCode(unsigned int i) const { |
314 | 30.9M | if (!dp_atoms[i].hasRingNbr) { |
315 | 30.9M | return 0; |
316 | 30.9M | } |
317 | | |
318 | 0 | const std::span<const int> nbrs = dp_atoms[i].nbrIds; |
319 | 0 | unsigned int code = 0; |
320 | 0 | for (unsigned j = 0; j < dp_atoms[i].degree; ++j) { |
321 | 0 | if (dp_atoms[nbrs[j]].isRingStereoAtom) { |
322 | 0 | code += dp_atoms[nbrs[j]].index * 10000 + 1; // j; |
323 | 0 | } |
324 | 0 | } |
325 | 0 | return code; |
326 | 30.9M | } |
327 | | |
328 | 17.4M | int basecomp(int i, int j) const { |
329 | 17.4M | unsigned int ivi, ivj; |
330 | | |
331 | | // always start with the current class: |
332 | 17.4M | ivi = dp_atoms[i].index; |
333 | 17.4M | ivj = dp_atoms[j].index; |
334 | 17.4M | if (ivi < ivj) { |
335 | 0 | return -1; |
336 | 17.4M | } else if (ivi > ivj) { |
337 | 0 | return 1; |
338 | 0 | } |
339 | | |
340 | 17.4M | if (df_useNonStereoRanks) { |
341 | | // use the non-stereo ranks if they were assigned |
342 | 0 | int rankingNumber_i = 0; |
343 | 0 | int rankingNumber_j = 0; |
344 | 0 | dp_atoms[i].atom->getPropIfPresent( |
345 | 0 | common_properties::_CanonicalRankingNumber, rankingNumber_i); |
346 | 0 | dp_atoms[j].atom->getPropIfPresent( |
347 | 0 | common_properties::_CanonicalRankingNumber, rankingNumber_j); |
348 | 0 | if (rankingNumber_i < rankingNumber_j) { |
349 | 0 | return -1; |
350 | 0 | } else if (rankingNumber_i > rankingNumber_j) { |
351 | 0 | return 1; |
352 | 0 | } |
353 | 0 | } |
354 | | |
355 | 17.4M | if (df_useAtomMaps || df_useAtomMapsOnDummies) { |
356 | | // use the atom-mapping numbers if they were assigned |
357 | 17.4M | int molAtomMapNumber_i = 0; |
358 | 17.4M | int molAtomMapNumber_j = 0; |
359 | 17.4M | if (df_useAtomMaps || |
360 | 17.4M | (df_useAtomMapsOnDummies && dp_atoms[i].atom->getAtomicNum() == 0)) { |
361 | 17.4M | dp_atoms[i].atom->getPropIfPresent(common_properties::molAtomMapNumber, |
362 | 17.4M | molAtomMapNumber_i); |
363 | 17.4M | } |
364 | 17.4M | if (df_useAtomMaps || |
365 | 17.4M | (df_useAtomMapsOnDummies && dp_atoms[j].atom->getAtomicNum() == 0)) { |
366 | 17.4M | dp_atoms[j].atom->getPropIfPresent(common_properties::molAtomMapNumber, |
367 | 17.4M | molAtomMapNumber_j); |
368 | 17.4M | } |
369 | 17.4M | if (molAtomMapNumber_i < molAtomMapNumber_j) { |
370 | 14.2k | return -1; |
371 | 17.4M | } else if (molAtomMapNumber_i > molAtomMapNumber_j) { |
372 | 8.28k | return 1; |
373 | 8.28k | } |
374 | 17.4M | } |
375 | | // start by comparing degree |
376 | 17.4M | ivi = dp_atoms[i].degree; |
377 | 17.4M | ivj = dp_atoms[j].degree; |
378 | 17.4M | if (ivi < ivj) { |
379 | 403k | return -1; |
380 | 17.0M | } else if (ivi > ivj) { |
381 | 490k | return 1; |
382 | 490k | } |
383 | 16.5M | if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) { |
384 | 0 | return dp_atoms[i].p_symbol->compare(*dp_atoms[j].p_symbol); |
385 | 0 | } |
386 | | |
387 | | // move onto atomic number |
388 | 16.5M | ivi = dp_atoms[i].atom->getAtomicNum(); |
389 | 16.5M | ivj = dp_atoms[j].atom->getAtomicNum(); |
390 | 16.5M | if (ivi < ivj) { |
391 | 491k | return -1; |
392 | 16.0M | } else if (ivi > ivj) { |
393 | 452k | return 1; |
394 | 452k | } |
395 | | // isotopes if we're using them |
396 | 15.6M | if (df_useIsotopes) { |
397 | 15.6M | ivi = dp_atoms[i].atom->getIsotope(); |
398 | 15.6M | ivj = dp_atoms[j].atom->getIsotope(); |
399 | 15.6M | if (ivi < ivj) { |
400 | 4.19k | return -1; |
401 | 15.6M | } else if (ivi > ivj) { |
402 | 4.56k | return 1; |
403 | 4.56k | } |
404 | 15.6M | } |
405 | | |
406 | | // nHs |
407 | 15.5M | ivi = dp_atoms[i].totalNumHs; |
408 | 15.5M | ivj = dp_atoms[j].totalNumHs; |
409 | 15.5M | if (ivi < ivj) { |
410 | 66.6k | return -1; |
411 | 15.5M | } else if (ivi > ivj) { |
412 | 66.2k | return 1; |
413 | 66.2k | } |
414 | | // charge |
415 | 15.4M | ivi = dp_atoms[i].atom->getFormalCharge(); |
416 | 15.4M | ivj = dp_atoms[j].atom->getFormalCharge(); |
417 | 15.4M | if (ivi < ivj) { |
418 | 4.39k | return -1; |
419 | 15.4M | } else if (ivi > ivj) { |
420 | 2.90k | return 1; |
421 | 2.90k | } |
422 | | // presence of specified chirality if it's being used |
423 | 15.4M | if (df_useChiralPresence) { |
424 | 0 | ivi = |
425 | 0 | dp_atoms[i].atom->getChiralTag() != Atom::ChiralType::CHI_UNSPECIFIED; |
426 | 0 | ivj = |
427 | 0 | dp_atoms[j].atom->getChiralTag() != Atom::ChiralType::CHI_UNSPECIFIED; |
428 | 0 | if (ivi < ivj) { |
429 | 0 | return -1; |
430 | 0 | } else if (ivi > ivj) { |
431 | 0 | return 1; |
432 | 0 | } |
433 | 0 | } |
434 | | // chirality if we're using it |
435 | 15.4M | if (df_useChirality) { |
436 | | // look at enhanced stereo - whichStereoGroup == 0 means no stereo |
437 | 15.4M | ivi = dp_atoms[i].whichStereoGroup; // can't use the index itself, but if |
438 | | // it's set then we're in an SG |
439 | 15.4M | ivj = dp_atoms[j].whichStereoGroup; |
440 | 15.4M | if (ivi || ivj) { |
441 | 0 | if (ivi && !ivj) { |
442 | 0 | return 1; |
443 | 0 | } else if (ivj && !ivi) { |
444 | 0 | return -1; |
445 | 0 | } else if (ivi && ivj) { |
446 | 0 | auto iType = dp_atoms[i].typeOfStereoGroup; |
447 | 0 | auto jType = dp_atoms[j].typeOfStereoGroup; |
448 | 0 | if (iType < jType) { |
449 | 0 | return -1; |
450 | 0 | } else if (iType > jType) { |
451 | 0 | return 1; |
452 | 0 | } |
453 | 0 | if (ivi != ivj) { |
454 | | // now check the current classes of the other members of the SG |
455 | 0 | std::set<unsigned int> sgi; |
456 | 0 | for (const auto sgat : |
457 | 0 | dp_mol->getStereoGroups()[ivi - 1].getAtoms()) { |
458 | 0 | sgi.insert(dp_atoms[sgat->getIdx()].index); |
459 | 0 | } |
460 | 0 | std::set<unsigned int> sgj; |
461 | 0 | for (const auto sgat : |
462 | 0 | dp_mol->getStereoGroups()[ivj - 1].getAtoms()) { |
463 | 0 | sgj.insert(dp_atoms[sgat->getIdx()].index); |
464 | 0 | } |
465 | 0 | if (sgi < sgj) { |
466 | 0 | return -1; |
467 | 0 | } else if (sgi > sgj) { |
468 | 0 | return 1; |
469 | 0 | } |
470 | 0 | } else { // same stereo group |
471 | 0 | if (iType == StereoGroupType::STEREO_ABSOLUTE) { |
472 | 0 | ivi = getChiralRank(dp_mol, dp_atoms, i); |
473 | 0 | ivj = getChiralRank(dp_mol, dp_atoms, j); |
474 | 0 | if (ivi < ivj) { |
475 | 0 | return -1; |
476 | 0 | } else if (ivi > ivj) { |
477 | 0 | return 1; |
478 | 0 | } |
479 | 0 | } |
480 | 0 | } |
481 | 0 | } |
482 | 15.4M | } else { |
483 | | // if there's no stereogroup, then use whatever atom stereochem is |
484 | | // specfied: |
485 | 15.4M | ivi = 0; |
486 | 15.4M | ivj = 0; |
487 | | // can't actually use values here, because they are arbitrary |
488 | 15.4M | ivi = dp_atoms[i].atom->getChiralTag() != 0; |
489 | 15.4M | ivj = dp_atoms[j].atom->getChiralTag() != 0; |
490 | 15.4M | if (ivi < ivj) { |
491 | 1.94k | return -1; |
492 | 15.4M | } else if (ivi > ivj) { |
493 | 2.00k | return 1; |
494 | 2.00k | } |
495 | | // stereo set |
496 | 15.4M | if (ivi && ivj) { |
497 | 56.1k | if (ivi) { |
498 | 56.1k | ivi = getChiralRank(dp_mol, dp_atoms, i); |
499 | 56.1k | } |
500 | 56.1k | if (ivj) { |
501 | 56.1k | ivj = getChiralRank(dp_mol, dp_atoms, j); |
502 | 56.1k | } |
503 | 56.1k | if (ivi < ivj) { |
504 | 1.36k | return -1; |
505 | 54.8k | } else if (ivi > ivj) { |
506 | 1.47k | return 1; |
507 | 1.47k | } |
508 | 56.1k | } |
509 | 15.4M | } |
510 | 15.4M | } |
511 | | |
512 | 15.4M | if (df_useChiralityRings) { |
513 | | // ring stereochemistry |
514 | 15.4M | ivi = getAtomRingNbrCode(i); |
515 | 15.4M | ivj = getAtomRingNbrCode(j); |
516 | 15.4M | if (ivi < ivj) { |
517 | 0 | return -1; |
518 | 15.4M | } else if (ivi > ivj) { |
519 | 0 | return 1; |
520 | 0 | } // bond stereo is taken care of in the neighborhood comparison |
521 | 15.4M | } |
522 | 15.4M | return 0; |
523 | 15.4M | } |
524 | | |
525 | | public: |
526 | | Canon::canon_atom *dp_atoms{nullptr}; |
527 | | const ROMol *dp_mol{nullptr}; |
528 | | const AtomCompareCode *dp_compareCodes{ |
529 | | nullptr}; // optional complete atom comparison keys |
530 | | const boost::dynamic_bitset<> *dp_atomsInPlay{nullptr}, |
531 | | *dp_bondsInPlay{nullptr}; |
532 | | bool df_useNbrs{false}; |
533 | | bool df_useIsotopes{true}; |
534 | | bool df_useChirality{true}; |
535 | | bool df_useChiralityRings{true}; |
536 | | bool df_useAtomMaps{true}; |
537 | | bool df_useNonStereoRanks{false}; |
538 | | bool df_useChiralPresence{true}; |
539 | | bool df_useAtomMapsOnDummies{true}; |
540 | | |
541 | 0 | AtomCompareFunctor() {} |
542 | | AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, |
543 | | const boost::dynamic_bitset<> *atomsInPlay = nullptr, |
544 | | const boost::dynamic_bitset<> *bondsInPlay = nullptr, |
545 | | const AtomCompareCode *compareCodes = nullptr) |
546 | 2.66k | : dp_atoms(atoms), |
547 | 2.66k | dp_mol(&m), |
548 | 2.66k | dp_compareCodes(compareCodes), |
549 | 2.66k | dp_atomsInPlay(atomsInPlay), |
550 | 2.66k | dp_bondsInPlay(bondsInPlay) {} |
551 | | |
552 | 17.4M | int operator()(int i, int j) const { |
553 | 17.4M | if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) { |
554 | 0 | return 0; |
555 | 0 | } |
556 | 17.4M | int v = 0; |
557 | 17.4M | if (dp_compareCodes) { |
558 | 0 | if (dp_atoms[i].index != dp_atoms[j].index) { |
559 | 0 | v = dp_atoms[i].index < dp_atoms[j].index ? -1 : 1; |
560 | 0 | } else { |
561 | 0 | const auto ordering = dp_compareCodes[i] <=> dp_compareCodes[j]; |
562 | 0 | if (ordering != 0) { |
563 | 0 | v = ordering < 0 ? -1 : 1; |
564 | 0 | } |
565 | 0 | } |
566 | 17.4M | } else { |
567 | 17.4M | v = basecomp(i, j); |
568 | 17.4M | } |
569 | 17.4M | if (v) { |
570 | 2.01M | return v; |
571 | 2.01M | } |
572 | | |
573 | 15.4M | if (df_useNbrs) { |
574 | 15.4M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) { |
575 | 15.4M | updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds); |
576 | 15.4M | } |
577 | 15.4M | if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) { |
578 | 15.4M | updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds); |
579 | 15.4M | } |
580 | | |
581 | 15.4M | for (unsigned int ii = 0; |
582 | 36.5M | ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); |
583 | 24.0M | ++ii) { |
584 | 24.0M | int cmp = |
585 | 24.0M | bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]); |
586 | 24.0M | if (cmp) { |
587 | 2.98M | return cmp; |
588 | 2.98M | } |
589 | 24.0M | } |
590 | | |
591 | 12.4M | if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) { |
592 | 0 | return -1; |
593 | 12.4M | } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) { |
594 | 0 | return 1; |
595 | 0 | } |
596 | 12.4M | } |
597 | 12.4M | return 0; |
598 | 15.4M | } |
599 | | }; |
600 | | |
601 | | /* |
602 | | * A compare function to discriminate chiral atoms, similar to the CIP rules. |
603 | | * This functionality is currently not used. |
604 | | */ |
605 | | |
606 | | const unsigned int ATNUM_CLASS_OFFSET = 10000; |
607 | | class RDKIT_GRAPHMOL_EXPORT ChiralAtomCompareFunctor { |
608 | 0 | void getAtomNeighborhood(BondholderVector &nbrs) const { |
609 | 0 | for (unsigned j = 0; j < nbrs.size(); ++j) { |
610 | 0 | unsigned int nbrIdx = nbrs[j].nbrIdx; |
611 | 0 | if (nbrIdx == ATNUM_CLASS_OFFSET) { |
612 | | // Ignore the Hs |
613 | 0 | continue; |
614 | 0 | } |
615 | 0 | const Atom *nbr = dp_atoms[nbrIdx].atom; |
616 | 0 | nbrs[j].nbrSymClass = |
617 | 0 | nbr->getAtomicNum() * ATNUM_CLASS_OFFSET + dp_atoms[nbrIdx].index + 1; |
618 | 0 | } |
619 | 0 | std::sort(nbrs.begin(), nbrs.end(), bondholder::greater); |
620 | | // FIX: don't want to be doing this long-term |
621 | 0 | } |
622 | | |
623 | 0 | int basecomp(int i, int j) const { |
624 | 0 | PRECONDITION(dp_atoms, "no atoms"); |
625 | 0 | unsigned int ivi, ivj; |
626 | | |
627 | | // always start with the current class: |
628 | 0 | ivi = dp_atoms[i].index; |
629 | 0 | ivj = dp_atoms[j].index; |
630 | 0 | if (ivi < ivj) { |
631 | 0 | return -1; |
632 | 0 | } else if (ivi > ivj) { |
633 | 0 | return 1; |
634 | 0 | } |
635 | | |
636 | | // move onto atomic number |
637 | 0 | ivi = dp_atoms[i].atom->getAtomicNum(); |
638 | 0 | ivj = dp_atoms[j].atom->getAtomicNum(); |
639 | 0 | if (ivi < ivj) { |
640 | 0 | return -1; |
641 | 0 | } else if (ivi > ivj) { |
642 | 0 | return 1; |
643 | 0 | } |
644 | | |
645 | | // isotopes: |
646 | 0 | ivi = dp_atoms[i].atom->getIsotope(); |
647 | 0 | ivj = dp_atoms[j].atom->getIsotope(); |
648 | 0 | if (ivi < ivj) { |
649 | 0 | return -1; |
650 | 0 | } else if (ivi > ivj) { |
651 | 0 | return 1; |
652 | 0 | } |
653 | | |
654 | | // atom stereochem: |
655 | 0 | ivi = 0; |
656 | 0 | ivj = 0; |
657 | 0 | std::string cipCode; |
658 | 0 | if (dp_atoms[i].atom->getPropIfPresent(common_properties::_CIPCode, |
659 | 0 | cipCode)) { |
660 | 0 | ivi = cipCode == "R" ? 2 : 1; |
661 | 0 | } |
662 | 0 | if (dp_atoms[j].atom->getPropIfPresent(common_properties::_CIPCode, |
663 | 0 | cipCode)) { |
664 | 0 | ivj = cipCode == "R" ? 2 : 1; |
665 | 0 | } |
666 | 0 | if (ivi < ivj) { |
667 | 0 | return -1; |
668 | 0 | } else if (ivi > ivj) { |
669 | 0 | return 1; |
670 | 0 | } |
671 | | |
672 | | // bond stereo is taken care of in the neighborhood comparison |
673 | 0 | return 0; |
674 | 0 | } |
675 | | |
676 | | public: |
677 | | Canon::canon_atom *dp_atoms{nullptr}; |
678 | | const ROMol *dp_mol{nullptr}; |
679 | | bool df_useNbrs{false}; |
680 | 0 | ChiralAtomCompareFunctor() {} |
681 | | ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m) |
682 | 0 | : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false) {} |
683 | 0 | int operator()(int i, int j) const { |
684 | 0 | PRECONDITION(dp_atoms, "no atoms"); |
685 | 0 | PRECONDITION(dp_mol, "no molecule"); |
686 | 0 | PRECONDITION(i != j, "bad call"); |
687 | 0 | int v = basecomp(i, j); |
688 | 0 | if (v) { |
689 | 0 | return v; |
690 | 0 | } |
691 | | |
692 | 0 | if (df_useNbrs) { |
693 | 0 | getAtomNeighborhood(dp_atoms[i].bonds); |
694 | 0 | getAtomNeighborhood(dp_atoms[j].bonds); |
695 | | |
696 | | // we do two passes through the neighbor lists. The first just uses the |
697 | | // atomic numbers (by passing the optional 10000 to bondholder::compare), |
698 | | // the second takes the already-computed index into account |
699 | 0 | for (unsigned int ii = 0; |
700 | 0 | ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); |
701 | 0 | ++ii) { |
702 | 0 | int cmp = bondholder::compare( |
703 | 0 | dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii], ATNUM_CLASS_OFFSET); |
704 | 0 | if (cmp) { |
705 | 0 | return cmp; |
706 | 0 | } |
707 | 0 | } |
708 | 0 | for (unsigned int ii = 0; |
709 | 0 | ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); |
710 | 0 | ++ii) { |
711 | 0 | int cmp = |
712 | 0 | bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]); |
713 | 0 | if (cmp) { |
714 | 0 | return cmp; |
715 | 0 | } |
716 | 0 | } |
717 | 0 | if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) { |
718 | 0 | return -1; |
719 | 0 | } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) { |
720 | 0 | return 1; |
721 | 0 | } |
722 | 0 | } |
723 | 0 | return 0; |
724 | 0 | } |
725 | | }; |
726 | | |
727 | | /* |
728 | | * Basic canonicalization function to organize the partitions which will be |
729 | | * sorted next. |
730 | | * */ |
731 | | |
732 | | template <typename CompareFunc> |
733 | | void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, |
734 | | int mode, std::vector<int> &order, |
735 | | std::vector<int> &count, int &activeset, |
736 | | std::vector<int> &next, std::vector<int> &changed, |
737 | | std::vector<char> &touchedPartitions, |
738 | 144k | std::vector<int> *hanoiTemp = nullptr) { |
739 | 144k | unsigned int nAtoms = mol.getNumAtoms(); |
740 | 144k | std::vector<int> localHanoiTemp; |
741 | 144k | if (!hanoiTemp) { |
742 | 0 | localHanoiTemp.resize(nAtoms); |
743 | 0 | hanoiTemp = &localHanoiTemp; |
744 | 0 | } |
745 | 144k | int partition; |
746 | 144k | int symclass = 0; |
747 | 144k | int offset; |
748 | 144k | int index; |
749 | 144k | int len; |
750 | 144k | int i; |
751 | 144k | PRECONDITION(hanoiTemp->size() >= nAtoms, "hanoi scratch is too small"); |
752 | | // std::vector<char> touchedPartitions(mol.getNumAtoms(),0); |
753 | | |
754 | | // std::cerr<<"&&&&&&&&&&&&&&&& RP"<<std::endl; |
755 | 988k | while (activeset != -1) { |
756 | | // std::cerr<<"ITER: "<<activeset<<" next: "<<next[activeset]<<std::endl; |
757 | | // std::cerr<<" next: "; |
758 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ |
759 | | // std::cerr<<ii<<":"<<next[ii]<<" "; |
760 | | // } |
761 | | // std::cerr<<std::endl; |
762 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ |
763 | | // std::cerr<<order[ii]<<" count: "<<count[order[ii]]<<" index: |
764 | | // "<<atoms[order[ii]].index<<std::endl; |
765 | | // } |
766 | | |
767 | 843k | partition = activeset; |
768 | 843k | activeset = next[partition]; |
769 | 843k | next[partition] = -2; |
770 | | |
771 | 843k | len = count[partition]; |
772 | 843k | offset = atoms[partition].index; |
773 | 843k | auto start = std::span<int>(&order[offset], len); |
774 | | // std::cerr<<"\n\n**************************************************************"<<std::endl; |
775 | | // std::cerr<<" sort - class:"<<atoms[partition].index<<" len: |
776 | | // "<<len<<":"; for(unsigned int ii=0;ii<len;++ii){ |
777 | | // std::cerr<<" "<<order[offset+ii]+1; |
778 | | // } |
779 | | // std::cerr<<std::endl; |
780 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ |
781 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: |
782 | | // "<<atoms[order[ii]].index<<std::endl; |
783 | | // } |
784 | 843k | if (RDKit::detail::hanoi(start.data(), len, hanoiTemp->data(), count.data(), |
785 | 843k | changed.data(), compar)) { |
786 | 401k | std::copy_n(hanoiTemp->begin(), len, start.begin()); |
787 | 401k | } |
788 | | // std::cerr<<"*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"<<std::endl; |
789 | | // std::cerr<<" result:"; |
790 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ |
791 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: |
792 | | // "<<atoms[order[ii]].index<<std::endl; |
793 | | // } |
794 | 87.6M | for (int k = 0; k < len; ++k) { |
795 | 86.7M | changed[start[k]] = 0; |
796 | 86.7M | } |
797 | | |
798 | 843k | index = start[0]; |
799 | | // std::cerr<<" len:"<<len<<" index:"<<index<<" |
800 | | // count:"<<count[index]<<std::endl; |
801 | 12.7M | for (i = count[index]; i < len; i++) { |
802 | 11.9M | index = start[i]; |
803 | 11.9M | if (count[index]) { |
804 | 879k | symclass = offset + i; |
805 | 879k | } |
806 | 11.9M | atoms[index].index = symclass; |
807 | | // std::cerr<<" "<<index+1<<"("<<symclass<<")"; |
808 | | // if(mode && (activeset<0 || count[index]>count[activeset]) ){ |
809 | | // activeset=index; |
810 | | //} |
811 | 30.4M | for (unsigned j = 0; j < atoms[index].degree; ++j) { |
812 | 18.5M | changed[atoms[index].nbrIds[j]] = 1; |
813 | 18.5M | } |
814 | 11.9M | } |
815 | | // std::cerr<<std::endl; |
816 | | |
817 | 843k | if (mode) { |
818 | 843k | index = start[0]; |
819 | 12.7M | for (i = count[index]; i < len; i++) { |
820 | 11.9M | index = start[i]; |
821 | 30.4M | for (unsigned j = 0; j < atoms[index].degree; ++j) { |
822 | 18.5M | unsigned int nbor = atoms[index].nbrIds[j]; |
823 | 18.5M | touchedPartitions[atoms[nbor].index] = 1; |
824 | 18.5M | } |
825 | 11.9M | } |
826 | 29.8G | for (unsigned int ii = 0; ii < nAtoms; ++ii) { |
827 | 29.8G | if (touchedPartitions[ii]) { |
828 | 1.51M | partition = order[ii]; |
829 | 1.51M | if ((count[partition] > 1) && (next[partition] == -2)) { |
830 | 652k | next[partition] = activeset; |
831 | 652k | activeset = partition; |
832 | 652k | } |
833 | 1.51M | touchedPartitions[ii] = 0; |
834 | 1.51M | } |
835 | 29.8G | } |
836 | 843k | } |
837 | 843k | } |
838 | 144k | } // end of RefinePartitions() void RDKit::Canon::RefinePartitions<RDKit::Canon::AtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::AtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) Line | Count | Source | 738 | 142k | std::vector<int> *hanoiTemp = nullptr) { | 739 | 142k | unsigned int nAtoms = mol.getNumAtoms(); | 740 | 142k | std::vector<int> localHanoiTemp; | 741 | 142k | if (!hanoiTemp) { | 742 | 0 | localHanoiTemp.resize(nAtoms); | 743 | 0 | hanoiTemp = &localHanoiTemp; | 744 | 0 | } | 745 | 142k | int partition; | 746 | 142k | int symclass = 0; | 747 | 142k | int offset; | 748 | 142k | int index; | 749 | 142k | int len; | 750 | 142k | int i; | 751 | 142k | PRECONDITION(hanoiTemp->size() >= nAtoms, "hanoi scratch is too small"); | 752 | | // std::vector<char> touchedPartitions(mol.getNumAtoms(),0); | 753 | | | 754 | | // std::cerr<<"&&&&&&&&&&&&&&&& RP"<<std::endl; | 755 | 932k | while (activeset != -1) { | 756 | | // std::cerr<<"ITER: "<<activeset<<" next: "<<next[activeset]<<std::endl; | 757 | | // std::cerr<<" next: "; | 758 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 759 | | // std::cerr<<ii<<":"<<next[ii]<<" "; | 760 | | // } | 761 | | // std::cerr<<std::endl; | 762 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 763 | | // std::cerr<<order[ii]<<" count: "<<count[order[ii]]<<" index: | 764 | | // "<<atoms[order[ii]].index<<std::endl; | 765 | | // } | 766 | | | 767 | 790k | partition = activeset; | 768 | 790k | activeset = next[partition]; | 769 | 790k | next[partition] = -2; | 770 | | | 771 | 790k | len = count[partition]; | 772 | 790k | offset = atoms[partition].index; | 773 | 790k | auto start = std::span<int>(&order[offset], len); | 774 | | // std::cerr<<"\n\n**************************************************************"<<std::endl; | 775 | | // std::cerr<<" sort - class:"<<atoms[partition].index<<" len: | 776 | | // "<<len<<":"; for(unsigned int ii=0;ii<len;++ii){ | 777 | | // std::cerr<<" "<<order[offset+ii]+1; | 778 | | // } | 779 | | // std::cerr<<std::endl; | 780 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 781 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 782 | | // "<<atoms[order[ii]].index<<std::endl; | 783 | | // } | 784 | 790k | if (RDKit::detail::hanoi(start.data(), len, hanoiTemp->data(), count.data(), | 785 | 790k | changed.data(), compar)) { | 786 | 382k | std::copy_n(hanoiTemp->begin(), len, start.begin()); | 787 | 382k | } | 788 | | // std::cerr<<"*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"<<std::endl; | 789 | | // std::cerr<<" result:"; | 790 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 791 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 792 | | // "<<atoms[order[ii]].index<<std::endl; | 793 | | // } | 794 | 84.0M | for (int k = 0; k < len; ++k) { | 795 | 83.2M | changed[start[k]] = 0; | 796 | 83.2M | } | 797 | | | 798 | 790k | index = start[0]; | 799 | | // std::cerr<<" len:"<<len<<" index:"<<index<<" | 800 | | // count:"<<count[index]<<std::endl; | 801 | 12.6M | for (i = count[index]; i < len; i++) { | 802 | 11.9M | index = start[i]; | 803 | 11.9M | if (count[index]) { | 804 | 878k | symclass = offset + i; | 805 | 878k | } | 806 | 11.9M | atoms[index].index = symclass; | 807 | | // std::cerr<<" "<<index+1<<"("<<symclass<<")"; | 808 | | // if(mode && (activeset<0 || count[index]>count[activeset]) ){ | 809 | | // activeset=index; | 810 | | //} | 811 | 30.4M | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 812 | 18.5M | changed[atoms[index].nbrIds[j]] = 1; | 813 | 18.5M | } | 814 | 11.9M | } | 815 | | // std::cerr<<std::endl; | 816 | | | 817 | 790k | if (mode) { | 818 | 790k | index = start[0]; | 819 | 12.6M | for (i = count[index]; i < len; i++) { | 820 | 11.9M | index = start[i]; | 821 | 30.4M | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 822 | 18.5M | unsigned int nbor = atoms[index].nbrIds[j]; | 823 | 18.5M | touchedPartitions[atoms[nbor].index] = 1; | 824 | 18.5M | } | 825 | 11.9M | } | 826 | 28.4G | for (unsigned int ii = 0; ii < nAtoms; ++ii) { | 827 | 28.4G | if (touchedPartitions[ii]) { | 828 | 1.51M | partition = order[ii]; | 829 | 1.51M | if ((count[partition] > 1) && (next[partition] == -2)) { | 830 | 652k | next[partition] = activeset; | 831 | 652k | activeset = partition; | 832 | 652k | } | 833 | 1.51M | touchedPartitions[ii] = 0; | 834 | 1.51M | } | 835 | 28.4G | } | 836 | 790k | } | 837 | 790k | } | 838 | 142k | } // end of RefinePartitions() |
void RDKit::Canon::RefinePartitions<RDKit::Canon::SpecialChiralityAtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::SpecialChiralityAtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) Line | Count | Source | 738 | 2.02k | std::vector<int> *hanoiTemp = nullptr) { | 739 | 2.02k | unsigned int nAtoms = mol.getNumAtoms(); | 740 | 2.02k | std::vector<int> localHanoiTemp; | 741 | 2.02k | if (!hanoiTemp) { | 742 | 0 | localHanoiTemp.resize(nAtoms); | 743 | 0 | hanoiTemp = &localHanoiTemp; | 744 | 0 | } | 745 | 2.02k | int partition; | 746 | 2.02k | int symclass = 0; | 747 | 2.02k | int offset; | 748 | 2.02k | int index; | 749 | 2.02k | int len; | 750 | 2.02k | int i; | 751 | 2.02k | PRECONDITION(hanoiTemp->size() >= nAtoms, "hanoi scratch is too small"); | 752 | | // std::vector<char> touchedPartitions(mol.getNumAtoms(),0); | 753 | | | 754 | | // std::cerr<<"&&&&&&&&&&&&&&&& RP"<<std::endl; | 755 | 47.3k | while (activeset != -1) { | 756 | | // std::cerr<<"ITER: "<<activeset<<" next: "<<next[activeset]<<std::endl; | 757 | | // std::cerr<<" next: "; | 758 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 759 | | // std::cerr<<ii<<":"<<next[ii]<<" "; | 760 | | // } | 761 | | // std::cerr<<std::endl; | 762 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 763 | | // std::cerr<<order[ii]<<" count: "<<count[order[ii]]<<" index: | 764 | | // "<<atoms[order[ii]].index<<std::endl; | 765 | | // } | 766 | | | 767 | 45.3k | partition = activeset; | 768 | 45.3k | activeset = next[partition]; | 769 | 45.3k | next[partition] = -2; | 770 | | | 771 | 45.3k | len = count[partition]; | 772 | 45.3k | offset = atoms[partition].index; | 773 | 45.3k | auto start = std::span<int>(&order[offset], len); | 774 | | // std::cerr<<"\n\n**************************************************************"<<std::endl; | 775 | | // std::cerr<<" sort - class:"<<atoms[partition].index<<" len: | 776 | | // "<<len<<":"; for(unsigned int ii=0;ii<len;++ii){ | 777 | | // std::cerr<<" "<<order[offset+ii]+1; | 778 | | // } | 779 | | // std::cerr<<std::endl; | 780 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 781 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 782 | | // "<<atoms[order[ii]].index<<std::endl; | 783 | | // } | 784 | 45.3k | if (RDKit::detail::hanoi(start.data(), len, hanoiTemp->data(), count.data(), | 785 | 45.3k | changed.data(), compar)) { | 786 | 14.7k | std::copy_n(hanoiTemp->begin(), len, start.begin()); | 787 | 14.7k | } | 788 | | // std::cerr<<"*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"<<std::endl; | 789 | | // std::cerr<<" result:"; | 790 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 791 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 792 | | // "<<atoms[order[ii]].index<<std::endl; | 793 | | // } | 794 | 3.35M | for (int k = 0; k < len; ++k) { | 795 | 3.30M | changed[start[k]] = 0; | 796 | 3.30M | } | 797 | | | 798 | 45.3k | index = start[0]; | 799 | | // std::cerr<<" len:"<<len<<" index:"<<index<<" | 800 | | // count:"<<count[index]<<std::endl; | 801 | 45.7k | for (i = count[index]; i < len; i++) { | 802 | 388 | index = start[i]; | 803 | 388 | if (count[index]) { | 804 | 381 | symclass = offset + i; | 805 | 381 | } | 806 | 388 | atoms[index].index = symclass; | 807 | | // std::cerr<<" "<<index+1<<"("<<symclass<<")"; | 808 | | // if(mode && (activeset<0 || count[index]>count[activeset]) ){ | 809 | | // activeset=index; | 810 | | //} | 811 | 1.66k | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 812 | 1.27k | changed[atoms[index].nbrIds[j]] = 1; | 813 | 1.27k | } | 814 | 388 | } | 815 | | // std::cerr<<std::endl; | 816 | | | 817 | 45.3k | if (mode) { | 818 | 45.3k | index = start[0]; | 819 | 45.7k | for (i = count[index]; i < len; i++) { | 820 | 388 | index = start[i]; | 821 | 1.66k | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 822 | 1.27k | unsigned int nbor = atoms[index].nbrIds[j]; | 823 | 1.27k | touchedPartitions[atoms[nbor].index] = 1; | 824 | 1.27k | } | 825 | 388 | } | 826 | 1.21G | for (unsigned int ii = 0; ii < nAtoms; ++ii) { | 827 | 1.21G | if (touchedPartitions[ii]) { | 828 | 1.05k | partition = order[ii]; | 829 | 1.05k | if ((count[partition] > 1) && (next[partition] == -2)) { | 830 | 58 | next[partition] = activeset; | 831 | 58 | activeset = partition; | 832 | 58 | } | 833 | 1.05k | touchedPartitions[ii] = 0; | 834 | 1.05k | } | 835 | 1.21G | } | 836 | 45.3k | } | 837 | 45.3k | } | 838 | 2.02k | } // end of RefinePartitions() |
void RDKit::Canon::RefinePartitions<RDKit::Canon::SpecialSymmetryAtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::SpecialSymmetryAtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) Line | Count | Source | 738 | 88 | std::vector<int> *hanoiTemp = nullptr) { | 739 | 88 | unsigned int nAtoms = mol.getNumAtoms(); | 740 | 88 | std::vector<int> localHanoiTemp; | 741 | 88 | if (!hanoiTemp) { | 742 | 0 | localHanoiTemp.resize(nAtoms); | 743 | 0 | hanoiTemp = &localHanoiTemp; | 744 | 0 | } | 745 | 88 | int partition; | 746 | 88 | int symclass = 0; | 747 | 88 | int offset; | 748 | 88 | int index; | 749 | 88 | int len; | 750 | 88 | int i; | 751 | 88 | PRECONDITION(hanoiTemp->size() >= nAtoms, "hanoi scratch is too small"); | 752 | | // std::vector<char> touchedPartitions(mol.getNumAtoms(),0); | 753 | | | 754 | | // std::cerr<<"&&&&&&&&&&&&&&&& RP"<<std::endl; | 755 | 8.02k | while (activeset != -1) { | 756 | | // std::cerr<<"ITER: "<<activeset<<" next: "<<next[activeset]<<std::endl; | 757 | | // std::cerr<<" next: "; | 758 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 759 | | // std::cerr<<ii<<":"<<next[ii]<<" "; | 760 | | // } | 761 | | // std::cerr<<std::endl; | 762 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 763 | | // std::cerr<<order[ii]<<" count: "<<count[order[ii]]<<" index: | 764 | | // "<<atoms[order[ii]].index<<std::endl; | 765 | | // } | 766 | | | 767 | 7.93k | partition = activeset; | 768 | 7.93k | activeset = next[partition]; | 769 | 7.93k | next[partition] = -2; | 770 | | | 771 | 7.93k | len = count[partition]; | 772 | 7.93k | offset = atoms[partition].index; | 773 | 7.93k | auto start = std::span<int>(&order[offset], len); | 774 | | // std::cerr<<"\n\n**************************************************************"<<std::endl; | 775 | | // std::cerr<<" sort - class:"<<atoms[partition].index<<" len: | 776 | | // "<<len<<":"; for(unsigned int ii=0;ii<len;++ii){ | 777 | | // std::cerr<<" "<<order[offset+ii]+1; | 778 | | // } | 779 | | // std::cerr<<std::endl; | 780 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 781 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 782 | | // "<<atoms[order[ii]].index<<std::endl; | 783 | | // } | 784 | 7.93k | if (RDKit::detail::hanoi(start.data(), len, hanoiTemp->data(), count.data(), | 785 | 7.93k | changed.data(), compar)) { | 786 | 3.86k | std::copy_n(hanoiTemp->begin(), len, start.begin()); | 787 | 3.86k | } | 788 | | // std::cerr<<"*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"<<std::endl; | 789 | | // std::cerr<<" result:"; | 790 | | // for(unsigned int ii=0;ii<nAtoms;++ii){ | 791 | | // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index: | 792 | | // "<<atoms[order[ii]].index<<std::endl; | 793 | | // } | 794 | 215k | for (int k = 0; k < len; ++k) { | 795 | 207k | changed[start[k]] = 0; | 796 | 207k | } | 797 | | | 798 | 7.93k | index = start[0]; | 799 | | // std::cerr<<" len:"<<len<<" index:"<<index<<" | 800 | | // count:"<<count[index]<<std::endl; | 801 | 10.1k | for (i = count[index]; i < len; i++) { | 802 | 2.24k | index = start[i]; | 803 | 2.24k | if (count[index]) { | 804 | 89 | symclass = offset + i; | 805 | 89 | } | 806 | 2.24k | atoms[index].index = symclass; | 807 | | // std::cerr<<" "<<index+1<<"("<<symclass<<")"; | 808 | | // if(mode && (activeset<0 || count[index]>count[activeset]) ){ | 809 | | // activeset=index; | 810 | | //} | 811 | 6.96k | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 812 | 4.72k | changed[atoms[index].nbrIds[j]] = 1; | 813 | 4.72k | } | 814 | 2.24k | } | 815 | | // std::cerr<<std::endl; | 816 | | | 817 | 7.93k | if (mode) { | 818 | 7.93k | index = start[0]; | 819 | 10.1k | for (i = count[index]; i < len; i++) { | 820 | 2.24k | index = start[i]; | 821 | 6.96k | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 822 | 4.72k | unsigned int nbor = atoms[index].nbrIds[j]; | 823 | 4.72k | touchedPartitions[atoms[nbor].index] = 1; | 824 | 4.72k | } | 825 | 2.24k | } | 826 | 239M | for (unsigned int ii = 0; ii < nAtoms; ++ii) { | 827 | 239M | if (touchedPartitions[ii]) { | 828 | 83 | partition = order[ii]; | 829 | 83 | if ((count[partition] > 1) && (next[partition] == -2)) { | 830 | 57 | next[partition] = activeset; | 831 | 57 | activeset = partition; | 832 | 57 | } | 833 | 83 | touchedPartitions[ii] = 0; | 834 | 83 | } | 835 | 239M | } | 836 | 7.93k | } | 837 | 7.93k | } | 838 | 88 | } // end of RefinePartitions() |
Unexecuted instantiation: void RDKit::Canon::RefinePartitions<RDKit::Canon::ChiralAtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::ChiralAtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) |
839 | | |
840 | | template <typename CompareFunc> |
841 | | void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, |
842 | | int mode, std::vector<int> &order, std::vector<int> &count, |
843 | | int &activeset, std::vector<int> &next, |
844 | | std::vector<int> &changed, std::vector<char> &touchedPartitions, |
845 | 2.66k | std::vector<int> *hanoiTemp = nullptr) { |
846 | 2.66k | unsigned int nAtoms = mol.getNumAtoms(); |
847 | 2.66k | int partition; |
848 | 2.66k | int offset; |
849 | 2.66k | int index; |
850 | 2.66k | int len; |
851 | 2.66k | int oldPart = 0; |
852 | | |
853 | 3.47M | for (unsigned int i = 0; i < nAtoms; i++) { |
854 | 3.46M | partition = order[i]; |
855 | 3.46M | oldPart = atoms[partition].index; |
856 | 6.05M | while (count[partition] > 1) { |
857 | 2.58M | len = count[partition]; |
858 | 2.58M | offset = atoms[partition].index + len - 1; |
859 | 2.58M | index = order[offset]; |
860 | 2.58M | atoms[index].index = offset; |
861 | 2.58M | count[partition] = len - 1; |
862 | 2.58M | count[index] = 1; |
863 | | |
864 | | // test for ions, water molecules with no |
865 | 2.58M | if (atoms[index].degree < 1) { |
866 | 2.44M | continue; |
867 | 2.44M | } |
868 | 281k | for (unsigned j = 0; j < atoms[index].degree; ++j) { |
869 | 141k | unsigned int nbor = atoms[index].nbrIds[j]; |
870 | 141k | touchedPartitions[atoms[nbor].index] = 1; |
871 | 141k | changed[nbor] = 1; |
872 | 141k | } |
873 | | |
874 | 5.34G | for (unsigned int ii = 0; ii < nAtoms; ++ii) { |
875 | 5.34G | if (touchedPartitions[ii]) { |
876 | 141k | int npart = order[ii]; |
877 | 141k | if ((count[npart] > 1) && (next[npart] == -2)) { |
878 | 134k | next[npart] = activeset; |
879 | 134k | activeset = npart; |
880 | 134k | } |
881 | 141k | touchedPartitions[ii] = 0; |
882 | 141k | } |
883 | 5.34G | } |
884 | 139k | RefinePartitions(mol, atoms, compar, mode, order, count, activeset, next, |
885 | 139k | changed, touchedPartitions, hanoiTemp); |
886 | 139k | } |
887 | | // not sure if this works each time |
888 | 3.46M | if (atoms[partition].index != oldPart) { |
889 | 47 | i -= 1; |
890 | 47 | } |
891 | 3.46M | } |
892 | 2.66k | } // end of BreakTies() void RDKit::Canon::BreakTies<RDKit::Canon::AtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::AtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) Line | Count | Source | 845 | 2.66k | std::vector<int> *hanoiTemp = nullptr) { | 846 | 2.66k | unsigned int nAtoms = mol.getNumAtoms(); | 847 | 2.66k | int partition; | 848 | 2.66k | int offset; | 849 | 2.66k | int index; | 850 | 2.66k | int len; | 851 | 2.66k | int oldPart = 0; | 852 | | | 853 | 3.47M | for (unsigned int i = 0; i < nAtoms; i++) { | 854 | 3.46M | partition = order[i]; | 855 | 3.46M | oldPart = atoms[partition].index; | 856 | 6.05M | while (count[partition] > 1) { | 857 | 2.58M | len = count[partition]; | 858 | 2.58M | offset = atoms[partition].index + len - 1; | 859 | 2.58M | index = order[offset]; | 860 | 2.58M | atoms[index].index = offset; | 861 | 2.58M | count[partition] = len - 1; | 862 | 2.58M | count[index] = 1; | 863 | | | 864 | | // test for ions, water molecules with no | 865 | 2.58M | if (atoms[index].degree < 1) { | 866 | 2.44M | continue; | 867 | 2.44M | } | 868 | 281k | for (unsigned j = 0; j < atoms[index].degree; ++j) { | 869 | 141k | unsigned int nbor = atoms[index].nbrIds[j]; | 870 | 141k | touchedPartitions[atoms[nbor].index] = 1; | 871 | 141k | changed[nbor] = 1; | 872 | 141k | } | 873 | | | 874 | 5.34G | for (unsigned int ii = 0; ii < nAtoms; ++ii) { | 875 | 5.34G | if (touchedPartitions[ii]) { | 876 | 141k | int npart = order[ii]; | 877 | 141k | if ((count[npart] > 1) && (next[npart] == -2)) { | 878 | 134k | next[npart] = activeset; | 879 | 134k | activeset = npart; | 880 | 134k | } | 881 | 141k | touchedPartitions[ii] = 0; | 882 | 141k | } | 883 | 5.34G | } | 884 | 139k | RefinePartitions(mol, atoms, compar, mode, order, count, activeset, next, | 885 | 139k | changed, touchedPartitions, hanoiTemp); | 886 | 139k | } | 887 | | // not sure if this works each time | 888 | 3.46M | if (atoms[partition].index != oldPart) { | 889 | 47 | i -= 1; | 890 | 47 | } | 891 | 3.46M | } | 892 | 2.66k | } // end of BreakTies() |
Unexecuted instantiation: void RDKit::Canon::BreakTies<RDKit::Canon::ChiralAtomCompareFunctor>(RDKit::ROMol const&, RDKit::Canon::canon_atom*, RDKit::Canon::ChiralAtomCompareFunctor, int, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, int&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<int, std::__1::allocator<int> >*) |
893 | | |
894 | | RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, |
895 | | std::vector<int> &order, |
896 | | std::vector<int> &count, |
897 | | canon_atom *atoms); |
898 | | |
899 | | RDKIT_GRAPHMOL_EXPORT void ActivatePartitions( |
900 | | unsigned int nAtoms, std::vector<int> &order, std::vector<int> &count, |
901 | | int &activeset, std::vector<int> &next, std::vector<int> &changed); |
902 | | |
903 | | //! Note that atom maps on dummy atoms will always be used |
904 | | RDKIT_GRAPHMOL_EXPORT void rankMolAtoms( |
905 | | const ROMol &mol, std::vector<unsigned int> &res, bool breakTies = true, |
906 | | bool includeChirality = true, bool includeIsotopes = true, |
907 | | bool includeAtomMaps = true, bool includeChiralPresence = false, |
908 | | bool includeStereoGroups = true, bool useNonStereoRanks = false, |
909 | | bool includeRingStereo = true); |
910 | | |
911 | | //! Note that atom maps on dummy atoms will always be used |
912 | | RDKIT_GRAPHMOL_EXPORT void rankFragmentAtoms( |
913 | | const ROMol &mol, std::vector<unsigned int> &res, |
914 | | const boost::dynamic_bitset<> &atomsInPlay, |
915 | | const boost::dynamic_bitset<> &bondsInPlay, |
916 | | const std::vector<std::string> *atomSymbols, |
917 | | const std::vector<std::string> *bondSymbols, bool breakTies, |
918 | | bool includeChirality, bool includeIsotope, bool includeAtomMaps, |
919 | | bool includeChiralPresence, bool includeRingStereo = true); |
920 | | |
921 | | //! Note that atom maps on dummy atoms will always be used |
922 | | inline void rankFragmentAtoms( |
923 | | const ROMol &mol, std::vector<unsigned int> &res, |
924 | | const boost::dynamic_bitset<> &atomsInPlay, |
925 | | const boost::dynamic_bitset<> &bondsInPlay, |
926 | | const std::vector<std::string> *atomSymbols = nullptr, |
927 | | bool breakTies = true, bool includeChirality = true, |
928 | | bool includeIsotopes = true, bool includeAtomMaps = true, |
929 | 1.15k | bool includeChiralPresence = false, bool includeRingStereo = true) { |
930 | 1.15k | rankFragmentAtoms(mol, res, atomsInPlay, bondsInPlay, atomSymbols, nullptr, |
931 | 1.15k | breakTies, includeChirality, includeIsotopes, |
932 | 1.15k | includeAtomMaps, includeChiralPresence, includeRingStereo); |
933 | 1.15k | }; |
934 | | |
935 | | RDKIT_GRAPHMOL_EXPORT void chiralRankMolAtoms(const ROMol &mol, |
936 | | std::vector<unsigned int> &res); |
937 | | |
938 | | RDKIT_GRAPHMOL_EXPORT void initCanonAtoms(const ROMol &mol, |
939 | | std::vector<Canon::canon_atom> &atoms, |
940 | | std::span<int> neighborIds, |
941 | | bool includeChirality = true, |
942 | | bool includeStereoGroups = true); |
943 | | |
944 | | namespace detail { |
945 | | void initFragmentCanonAtoms(const ROMol &mol, |
946 | | std::vector<Canon::canon_atom> &atoms, |
947 | | bool includeChirality, |
948 | | const std::vector<std::string> *atomSymbols, |
949 | | const std::vector<std::string> *bondSymbols, |
950 | | const boost::dynamic_bitset<> &atomsInPlay, |
951 | | const boost::dynamic_bitset<> &bondsInPlay, |
952 | | std::span<int> neighborIds, bool needsInit); |
953 | | template <typename T> |
954 | | void rankWithFunctor(T &ftor, bool breakTies, std::vector<int> &order, |
955 | | bool useSpecial = false, bool useChirality = false, |
956 | | bool includeRingStereo = true, |
957 | | const boost::dynamic_bitset<> *atomsInPlay = nullptr, |
958 | | const boost::dynamic_bitset<> *bondsInPlay = nullptr); |
959 | | |
960 | | } // namespace detail |
961 | | |
962 | | } // namespace Canon |
963 | | } // namespace RDKit |
964 | | |
965 | | #endif // RD_NEW_CANON_H |