RDKit
Open-source cheminformatics and machine learning.
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 
20 namespace RDKit {
21 
22 class Atom;
23 class Bond;
24 
25 namespace CIPLabeler {
26 
27 class Rules;
28 
30 
31 public:
32  template <typename T>
33  static int parity4(const std::vector<T> &trg, const std::vector<T> &ref) {
34  if (ref.size() != 4 || trg.size() != ref.size()) {
35  throw std::runtime_error("Parity vectors must have size 4.");
36  }
37 
38  if (ref[0] == trg[0]) {
39  if (ref[1] == trg[1]) {
40  // a,b,c,d -> a,b,c,d
41  if (ref[2] == trg[2] && ref[3] == trg[3])
42  return 2;
43  // a,b,c,d -> a,b,d,c
44  if (ref[2] == trg[3] && ref[3] == trg[2])
45  return 1;
46  } else if (ref[1] == trg[2]) {
47  // a,b,c,d -> a,c,b,d
48  if (ref[2] == trg[1] && ref[3] == trg[3])
49  return 1;
50  // a,b,c,d -> a,c,d,b
51  if (ref[2] == trg[3] && ref[3] == trg[1])
52  return 2;
53  } else if (ref[1] == trg[3]) {
54  // a,b,c,d -> a,d,c,b
55  if (ref[2] == trg[2] && ref[3] == trg[1])
56  return 1;
57  // a,b,c,d -> a,d,b,c
58  if (ref[2] == trg[1] && ref[3] == trg[2])
59  return 2;
60  }
61  } else if (ref[0] == trg[1]) {
62  if (ref[1] == trg[0]) {
63  // a,b,c,d -> b,a,c,d
64  if (ref[2] == trg[2] && ref[3] == trg[3])
65  return 1;
66  // a,b,c,d -> b,a,d,c
67  if (ref[2] == trg[3] && ref[3] == trg[2])
68  return 2;
69  } else if (ref[1] == trg[2]) {
70  // a,b,c,d -> b,c,a,d
71  if (ref[2] == trg[0] && ref[3] == trg[3])
72  return 2;
73  // a,b,c,d -> b,c,d,a
74  if (ref[2] == trg[3] && ref[3] == trg[0])
75  return 1;
76  } else if (ref[1] == trg[3]) {
77  // a,b,c,d -> b,d,c,a
78  if (ref[2] == trg[2] && ref[3] == trg[0])
79  return 2;
80  // a,b,c,d -> b,d,a,c
81  if (ref[2] == trg[0] && ref[3] == trg[2])
82  return 1;
83  }
84  } else if (ref[0] == trg[2]) {
85  if (ref[1] == trg[1]) {
86  // a,b,c,d -> c,b,a,d
87  if (ref[2] == trg[0] && ref[3] == trg[3])
88  return 1;
89  // a,b,c,d -> c,b,d,a
90  if (ref[2] == trg[3] && ref[3] == trg[0])
91  return 2;
92  } else if (ref[1] == trg[0]) {
93  // a,b,c,d -> c,a,b,d
94  if (ref[2] == trg[1] && ref[3] == trg[3])
95  return 2;
96  // a,b,c,d -> c,a,d,b
97  if (ref[2] == trg[3] && ref[3] == trg[1])
98  return 1;
99  } else if (ref[1] == trg[3]) {
100  // a,b,c,d -> c,d,a,b
101  if (ref[2] == trg[0] && ref[3] == trg[1])
102  return 2;
103  // a,b,c,d -> c,d,b,a
104  if (ref[2] == trg[1] && ref[3] == trg[0])
105  return 1;
106  }
107  } else if (ref[0] == trg[3]) {
108  if (ref[1] == trg[1]) {
109  // a,b,c,d -> d,b,c,a
110  if (ref[2] == trg[2] && ref[3] == trg[0])
111  return 1;
112  // a,b,c,d -> d,b,a,c
113  if (ref[2] == trg[0] && ref[3] == trg[2])
114  return 2;
115  } else if (ref[1] == trg[2]) {
116  // a,b,c,d -> d,c,b,a
117  if (ref[2] == trg[1] && ref[3] == trg[0])
118  return 2;
119  // a,b,c,d -> d,c,a,b
120  if (ref[2] == trg[0] && ref[3] == trg[1])
121  return 1;
122  } else if (ref[1] == trg[0]) {
123  // a,b,c,d -> d,a,c,b
124  if (ref[2] == trg[2] && ref[3] == trg[1])
125  return 2;
126  // a,b,c,d -> d,a,b,c
127  if (ref[2] == trg[1] && ref[3] == trg[2])
128  return 1;
129  }
130  }
131 
132  // We should never hit this, but the compiler still complains
133  // about a missing return statement.
134  return 0;
135  }
136 
137  Configuration() = delete;
138 
139  Configuration(const CIPMol &mol, Atom *focus);
140 
141  Configuration(const CIPMol &mol, std::vector<Atom *> &&foci);
142 
143  virtual ~Configuration();
144 
145  Atom *getFocus() const;
146 
147  const std::vector<Atom *> &getFoci() const;
148 
149  const std::vector<Atom *> &getCarriers() const;
150 
152 
153  virtual Descriptor label(Node *node, Digraph &digraph, const Rules &comp);
154 
155  virtual Descriptor label(const Rules &comp) = 0;
156 
157  virtual void setPrimaryLabel(Descriptor desc) = 0;
158 
159 protected:
160  Edge *findInternalEdge(const std::vector<Edge *> &edges, Atom *f1, Atom *f2);
161 
162  bool isInternalEdge(const Edge *edge, Atom *f1, Atom *f2);
163 
164  void removeInternalEdges(std::vector<Edge *> &edges, Atom *f1, Atom *f2);
165 
166  void setCarriers(std::vector<Atom *> &&carriers);
167 
168 private:
169  /**
170  * Foci are the atoms on which the configuration is based,
171  * and which will carry the label. E.g., the chiral atom in
172  * a tetrahedral chirality, or the bond ends in a double bond.
173  */
174  std::vector<Atom *> d_foci;
175 
176  /**
177  * Carriers are the atoms neighboring the foci that define the
178  * configuration. E.g., for a chiral atom, its four neighbors
179  * define a parity; for a double bond, one neighbor on each
180  * side of the bond defines it as Cis or Trans.
181  */
182  std::vector<Atom *> d_carriers;
183 
184  Digraph d_digraph;
185 
186 }; // namespace CIPLabeler
187 
188 } // namespace CIPLabeler
189 } // namespace RDKit
The class for representing atoms.
Definition: Atom.h:69
void setCarriers(std::vector< Atom * > &&carriers)
virtual Descriptor label(Node *node, Digraph &digraph, const Rules &comp)
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)
const std::vector< Atom * > & getFoci() const
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)
const std::vector< Atom * > & getCarriers() const
static int parity4(const std::vector< T > &trg, const std::vector< T > &ref)
Definition: Configuration.h:33
Std stuff.
Definition: Abbreviations.h:17