1 /*
2 * sketcherMinimizerMolecule.cpp
3 *
4 * Created by Nicola Zonta on 24/05/2011.
5 * Copyright Schrodinger, LLC. All rights reserved.
6 *
7 */
8
9 #include "sketcherMinimizerMolecule.h"
10 #include "sketcherMinimizerAtom.h"
11 #include "sketcherMinimizerMaths.h"
12 #include "sketcherMinimizerRing.h"
13 #include "sketcherMinimizerBond.h"
14 #include <queue>
15
16 using namespace std;
17
sketcherMinimizerMolecule()18 sketcherMinimizerMolecule::sketcherMinimizerMolecule()
19 : fixed(false),
20
21 hasFixedFragments(false), hasConstrainedFragments(false),
22 needToAlignNonRingAtoms(false), needToAlignWholeMolecule(false),
23 isPlaced(false), m_mainFragment(nullptr), m_requireMinimization(false){};
24
~sketcherMinimizerMolecule()25 sketcherMinimizerMolecule::~sketcherMinimizerMolecule()
26 {
27 for (auto ring : _rings) {
28 delete ring;
29 }
30 }
31
addNewAtom()32 sketcherMinimizerAtom* sketcherMinimizerMolecule::addNewAtom()
33 {
34 auto atom = new sketcherMinimizerAtom();
35 _atoms.push_back(atom);
36 atom->molecule = this;
37 return atom;
38 }
39
40 sketcherMinimizerBond*
addNewBond(sketcherMinimizerAtom * at1,sketcherMinimizerAtom * at2)41 sketcherMinimizerMolecule::addNewBond(sketcherMinimizerAtom* at1,
42 sketcherMinimizerAtom* at2)
43 {
44 auto bond = new sketcherMinimizerBond(at1, at2);
45 _bonds.push_back(bond);
46 return bond;
47 }
48
totalCharge()49 int sketcherMinimizerMolecule::totalCharge()
50 {
51 int charge = 0;
52 for (auto& _atom : _atoms) {
53 charge += _atom->charge;
54 }
55 return charge;
56 }
57
boundingBox(sketcherMinimizerPointF & min,sketcherMinimizerPointF & max)58 void sketcherMinimizerMolecule::boundingBox(sketcherMinimizerPointF& min,
59 sketcherMinimizerPointF& max)
60 {
61 min.setX(0.f);
62 min.setY(0.f);
63 max.setX(0.f);
64 max.setY(0.f);
65 if (_atoms.size()) {
66 min = _atoms[0]->coordinates;
67 max = _atoms[0]->coordinates;
68 for (auto a : _atoms) {
69 if (a->coordinates.x() < min.x()) {
70 min.setX(a->coordinates.x());
71 }
72 if (a->coordinates.y() < min.y()) {
73 min.setY(a->coordinates.y());
74 }
75 if (a->coordinates.x() > max.x()) {
76 max.setX(a->coordinates.x());
77 }
78 if (a->coordinates.y() > max.y()) {
79 max.setY(a->coordinates.y());
80 }
81 }
82 }
83 }
84
requireMinimization()85 void sketcherMinimizerMolecule::requireMinimization()
86 {
87 m_requireMinimization = true;
88 }
89
minimizationIsRequired()90 bool sketcherMinimizerMolecule::minimizationIsRequired()
91 {
92 return m_requireMinimization;
93 }
94
center()95 sketcherMinimizerPointF sketcherMinimizerMolecule::center()
96 {
97 if (!_atoms.size()) {
98 return sketcherMinimizerPointF(0.f, 0.f);
99 }
100 sketcherMinimizerPointF c(.0f, .0f);
101 for (auto& _atom : _atoms) {
102 c += _atom->coordinates;
103 }
104 return c / _atoms.size();
105 }
106
assignBondsAndNeighbors(std::vector<sketcherMinimizerAtom * > & atoms,std::vector<sketcherMinimizerBond * > & bonds)107 void sketcherMinimizerMolecule::assignBondsAndNeighbors(
108 std::vector<sketcherMinimizerAtom*>& atoms,
109 std::vector<sketcherMinimizerBond*>& bonds)
110 {
111 for (auto atom : atoms) {
112 atom->bonds.clear();
113 atom->neighbors.clear();
114 atom->residueInteractionPartners.clear();
115 atom->residueInteractions.clear();
116 atom->rings.clear();
117 }
118
119 for (auto bond : bonds) {
120
121 bond->rings.clear();
122
123 if (!bond->isResidueInteraction()) {
124 // bond->_rings.clear ();
125 bond->startAtom->bonds.push_back(bond);
126
127 bond->endAtom->neighbors.push_back(bond->startAtom);
128
129 bond->endAtom->bonds.push_back(bond);
130
131 bond->startAtom->neighbors.push_back(bond->endAtom);
132 } else {
133 bond->startAtom->residueInteractions.push_back(bond);
134
135 bond->endAtom->residueInteractionPartners.push_back(
136 bond->startAtom);
137
138 bond->endAtom->residueInteractions.push_back(bond);
139
140 bond->startAtom->residueInteractionPartners.push_back(
141 bond->endAtom);
142 }
143 }
144 for (auto& atom : atoms) {
145 if (atom->_implicitHs == -1) {
146 atom->_implicitHs = atom->findHsNumber();
147 }
148 }
149 }
150
forceUpdateStruct(std::vector<sketcherMinimizerAtom * > & atoms,std::vector<sketcherMinimizerBond * > & bonds,std::vector<sketcherMinimizerRing * > & rings)151 void sketcherMinimizerMolecule::forceUpdateStruct(
152 std::vector<sketcherMinimizerAtom*>& atoms,
153 std::vector<sketcherMinimizerBond*>& bonds,
154 std::vector<sketcherMinimizerRing*>& rings)
155 {
156 sketcherMinimizerMolecule::assignBondsAndNeighbors(atoms, bonds);
157
158 findRings(bonds, rings);
159 for (auto& bond : bonds) {
160 for (unsigned int j = 0; j < bond->rings.size(); j++) {
161 sketcherMinimizerRing* ring = bond->rings[j];
162 bool found = false;
163 for (auto& k : bond->startAtom->rings) {
164 if (k == ring) {
165 found = true;
166 break;
167 }
168 }
169 if (!found) {
170 bond->startAtom->rings.push_back(ring);
171 }
172 found = false;
173 for (auto& k : bond->endAtom->rings) {
174 if (k == ring) {
175 found = true;
176 break;
177 }
178 }
179 if (!found) {
180 bond->endAtom->rings.push_back(ring);
181 }
182 }
183 }
184
185 for (auto& atom : atoms) {
186 for (unsigned int j = 0; j < atom->rings.size(); j++) {
187 atom->rings[j]->_atoms.push_back(atom);
188 }
189 }
190 }
191
findRings(std::vector<sketcherMinimizerBond * > & bonds,std::vector<sketcherMinimizerRing * > & rings)192 void sketcherMinimizerMolecule::findRings(
193 std::vector<sketcherMinimizerBond*>& bonds,
194 std::vector<sketcherMinimizerRing*>& rings)
195 {
196 for (auto& ring : rings) {
197 delete ring;
198 }
199 rings.clear();
200 for (unsigned int i = 0; i < bonds.size(); i++) {
201 for (auto& bond : bonds) {
202 bond->_SSSRVisited = false;
203 bond->_SSSRParent = nullptr;
204 bond->_SSSRParentAtStart = true;
205 }
206
207 sketcherMinimizerBond* bond = bonds[i];
208
209 std::queue<sketcherMinimizerBond*> q;
210 bond->_SSSRVisited = true;
211 q.push(bond);
212 bool closedRing = false;
213 while (!q.empty() && !closedRing) {
214 sketcherMinimizerBond* lastBond = q.front();
215 q.pop();
216
217 sketcherMinimizerAtom* pivotAtom = lastBond->endAtom;
218 if (!lastBond->_SSSRParentAtStart) {
219 pivotAtom = lastBond->startAtom;
220 }
221 for (unsigned int j = 0; j < pivotAtom->bonds.size(); j++) {
222 sketcherMinimizerBond* nextBond = pivotAtom->bonds[j];
223 // sketcherMinimizerAtom *nextAtom = pivotAtom->neighbors[j];
224 if (nextBond == lastBond) {
225 continue;
226 }
227 if (nextBond->_SSSRVisited) {
228 if (nextBond == bond) {
229 addRing(closeRing(lastBond), rings);
230 closedRing = true;
231 }
232
233 } else {
234 if (nextBond->endAtom == pivotAtom) {
235 nextBond->_SSSRParentAtStart = false;
236 }
237 nextBond->_SSSRParent = lastBond;
238 nextBond->_SSSRVisited = true;
239 q.push(nextBond);
240 }
241 }
242 }
243 }
244 for (auto ring : rings) {
245 for (unsigned int j = 0; j < ring->_bonds.size(); j++) {
246 sketcherMinimizerBond* bond = ring->_bonds[j];
247 bond->rings.push_back(ring);
248 }
249 }
250 }
251
252 sketcherMinimizerRing*
closeRing(sketcherMinimizerBond * bond)253 sketcherMinimizerMolecule::closeRing(sketcherMinimizerBond* bond)
254 {
255 auto* ring = new sketcherMinimizerRing();
256 sketcherMinimizerBond* lastBond = bond;
257 while (lastBond) {
258 ring->_bonds.push_back(lastBond);
259 lastBond = lastBond->_SSSRParent;
260 }
261 return ring;
262 }
263
addRing(sketcherMinimizerRing * ring,std::vector<sketcherMinimizerRing * > & rings)264 void sketcherMinimizerMolecule::addRing(
265 sketcherMinimizerRing* ring, std::vector<sketcherMinimizerRing*>& rings)
266 {
267 bool found = false;
268 for (auto& i : rings) {
269 if (i->sameAs(ring)) {
270 found = true;
271 break;
272 }
273 }
274 if (!found) {
275 rings.push_back(ring);
276 } else {
277 delete ring;
278 }
279 }
280