RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
Configuration.h
Go to the documentation of this file.
1//
2//
3// Copyright (C) 2020 Schrödinger, LLC
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#pragma once
12
13#include <memory>
14#include <vector>
15
16#include "../Descriptor.h"
17#include "../Digraph.h"
18#include "../CIPMol.h"
19
20namespace RDKit {
21
22class Atom;
23class Bond;
24
25namespace CIPLabeler {
26
27// used to represent the index of implicit Hs
28inline constexpr unsigned int IMPLICITH =
29 std::numeric_limits<unsigned int>::max();
30
31class Rules;
32
34 public:
35 template <typename T>
36 static int parity4(const std::vector<T> &trg, const std::vector<T> &ref) {
37 if (ref.size() != 4 || trg.size() != ref.size()) {
38 throw std::runtime_error("Parity vectors must have size 4.");
39 }
40
41 if (ref[0] == trg[0]) {
42 if (ref[1] == trg[1]) {
43 // a,b,c,d -> a,b,c,d
44 if (ref[2] == trg[2] && ref[3] == trg[3]) {
45 return 2;
46 }
47 // a,b,c,d -> a,b,d,c
48 if (ref[2] == trg[3] && ref[3] == trg[2]) {
49 return 1;
50 }
51 } else if (ref[1] == trg[2]) {
52 // a,b,c,d -> a,c,b,d
53 if (ref[2] == trg[1] && ref[3] == trg[3]) {
54 return 1;
55 }
56 // a,b,c,d -> a,c,d,b
57 if (ref[2] == trg[3] && ref[3] == trg[1]) {
58 return 2;
59 }
60 } else if (ref[1] == trg[3]) {
61 // a,b,c,d -> a,d,c,b
62 if (ref[2] == trg[2] && ref[3] == trg[1]) {
63 return 1;
64 }
65 // a,b,c,d -> a,d,b,c
66 if (ref[2] == trg[1] && ref[3] == trg[2]) {
67 return 2;
68 }
69 }
70 } else if (ref[0] == trg[1]) {
71 if (ref[1] == trg[0]) {
72 // a,b,c,d -> b,a,c,d
73 if (ref[2] == trg[2] && ref[3] == trg[3]) {
74 return 1;
75 }
76 // a,b,c,d -> b,a,d,c
77 if (ref[2] == trg[3] && ref[3] == trg[2]) {
78 return 2;
79 }
80 } else if (ref[1] == trg[2]) {
81 // a,b,c,d -> b,c,a,d
82 if (ref[2] == trg[0] && ref[3] == trg[3]) {
83 return 2;
84 }
85 // a,b,c,d -> b,c,d,a
86 if (ref[2] == trg[3] && ref[3] == trg[0]) {
87 return 1;
88 }
89 } else if (ref[1] == trg[3]) {
90 // a,b,c,d -> b,d,c,a
91 if (ref[2] == trg[2] && ref[3] == trg[0]) {
92 return 2;
93 }
94 // a,b,c,d -> b,d,a,c
95 if (ref[2] == trg[0] && ref[3] == trg[2]) {
96 return 1;
97 }
98 }
99 } else if (ref[0] == trg[2]) {
100 if (ref[1] == trg[1]) {
101 // a,b,c,d -> c,b,a,d
102 if (ref[2] == trg[0] && ref[3] == trg[3]) {
103 return 1;
104 }
105 // a,b,c,d -> c,b,d,a
106 if (ref[2] == trg[3] && ref[3] == trg[0]) {
107 return 2;
108 }
109 } else if (ref[1] == trg[0]) {
110 // a,b,c,d -> c,a,b,d
111 if (ref[2] == trg[1] && ref[3] == trg[3]) {
112 return 2;
113 }
114 // a,b,c,d -> c,a,d,b
115 if (ref[2] == trg[3] && ref[3] == trg[1]) {
116 return 1;
117 }
118 } else if (ref[1] == trg[3]) {
119 // a,b,c,d -> c,d,a,b
120 if (ref[2] == trg[0] && ref[3] == trg[1]) {
121 return 2;
122 }
123 // a,b,c,d -> c,d,b,a
124 if (ref[2] == trg[1] && ref[3] == trg[0]) {
125 return 1;
126 }
127 }
128 } else if (ref[0] == trg[3]) {
129 if (ref[1] == trg[1]) {
130 // a,b,c,d -> d,b,c,a
131 if (ref[2] == trg[2] && ref[3] == trg[0]) {
132 return 1;
133 }
134 // a,b,c,d -> d,b,a,c
135 if (ref[2] == trg[0] && ref[3] == trg[2]) {
136 return 2;
137 }
138 } else if (ref[1] == trg[2]) {
139 // a,b,c,d -> d,c,b,a
140 if (ref[2] == trg[1] && ref[3] == trg[0]) {
141 return 2;
142 }
143 // a,b,c,d -> d,c,a,b
144 if (ref[2] == trg[0] && ref[3] == trg[1]) {
145 return 1;
146 }
147 } else if (ref[1] == trg[0]) {
148 // a,b,c,d -> d,a,c,b
149 if (ref[2] == trg[2] && ref[3] == trg[1]) {
150 return 2;
151 }
152 // a,b,c,d -> d,a,b,c
153 if (ref[2] == trg[1] && ref[3] == trg[2]) {
154 return 1;
155 }
156 }
157 }
158
159 // We should never hit this, but the compiler still complains
160 // about a missing return statement.
161 return 0;
162 }
163
164 Configuration() = delete;
165
166 Configuration(const CIPMol &mol, Atom *focus);
167
168 Configuration(const CIPMol &mol, std::vector<Atom *> &&foci,
169 bool atropisomerMode = false);
170
171 virtual ~Configuration();
172
173 Atom *getFocus() const;
174
175 const std::vector<Atom *> &getFoci() const;
176
177 const std::vector<Atom *> &getCarriers() const;
178
180
181 virtual Descriptor label(Node *node, Digraph &digraph, const Rules &comp);
182
183 virtual Descriptor label(const Rules &comp) = 0;
184
185 virtual void setPrimaryLabel(Descriptor desc) = 0;
186
187 virtual bool hasPrimaryLabel() const = 0;
188
189 virtual void resetPrimaryLabel() const = 0;
190
191 protected:
192 Edge *findInternalEdge(const std::vector<Edge *> &edges, Atom *f1, Atom *f2);
193
194 bool isInternalEdge(const Edge *edge, Atom *f1, Atom *f2);
195
196 void removeInternalEdges(std::vector<Edge *> &edges, Atom *f1, Atom *f2);
197
199
200 void removeDuplicatesAndHs(std::vector<Edge *> &edges);
201
202 void setCarriers(std::vector<Atom *> &&carriers);
203
204 private:
205 /**
206 * Foci are the atoms on which the configuration is based,
207 * and which will carry the label. E.g., the chiral atom in
208 * a tetrahedral chirality, or the bond ends in a double bond.
209 */
210 std::vector<Atom *> d_foci;
211
212 /**
213 * Carriers are the atoms neighboring the foci that define the
214 * configuration. E.g., for a chiral atom, its four neighbors
215 * define a parity; for a double bond, one neighbor on each
216 * side of the bond defines it as Cis or Trans.
217 */
218 std::vector<Atom *> d_carriers;
219
220 Digraph d_digraph;
221
222}; // namespace CIPLabeler
223
224} // namespace CIPLabeler
225} // namespace RDKit
The class for representing atoms.
Definition Atom.h:74
class for representing a bond
Definition Bond.h:46
void setCarriers(std::vector< Atom * > &&carriers)
virtual void resetPrimaryLabel() const =0
virtual Descriptor label(Node *node, Digraph &digraph, const Rules &comp)
bool isDuplicateOrHydrogenEdge(const Edge *edge)
const std::vector< Atom * > & getFoci() const
void removeDuplicatesAndHs(std::vector< Edge * > &edges)
const std::vector< Atom * > & getCarriers() const
Edge * findInternalEdge(const std::vector< Edge * > &edges, Atom *f1, Atom *f2)
virtual void setPrimaryLabel(Descriptor desc)=0
void removeInternalEdges(std::vector< Edge * > &edges, Atom *f1, Atom *f2)
bool isInternalEdge(const Edge *edge, Atom *f1, Atom *f2)
Configuration(const CIPMol &mol, Atom *focus)
virtual Descriptor label(const Rules &comp)=0
Configuration(const CIPMol &mol, std::vector< Atom * > &&foci, bool atropisomerMode=false)
static int parity4(const std::vector< T > &trg, const std::vector< T > &ref)
virtual bool hasPrimaryLabel() const =0
constexpr unsigned int IMPLICITH
Std stuff.