/src/openbabel/src/generic.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************** |
2 | | generic.cpp - Handle OBGenericData classes. |
3 | | |
4 | | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. |
5 | | Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison |
6 | | Some portions Copyright (C) 2010 by David Lonie |
7 | | |
8 | | This file is part of the Open Babel project. |
9 | | For more information, see <http://openbabel.org/> |
10 | | |
11 | | This program is free software; you can redistribute it and/or modify |
12 | | it under the terms of the GNU General Public License as published by |
13 | | the Free Software Foundation version 2 of the License. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, |
16 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | GNU General Public License for more details. |
19 | | ***********************************************************************/ |
20 | | #include <openbabel/babelconfig.h> |
21 | | |
22 | | #include <string> |
23 | | #include <set> |
24 | | |
25 | | #include <openbabel/mol.h> |
26 | | #include <openbabel/atom.h> |
27 | | #include <openbabel/bond.h> |
28 | | #include <openbabel/ring.h> |
29 | | #include <openbabel/obiter.h> |
30 | | #include <openbabel/generic.h> |
31 | | #include <openbabel/math/matrix3x3.h> |
32 | | #include <openbabel/elements.h> |
33 | | |
34 | | // needed for msvc to have at least one reference to AtomClass, AliasData in openbabel library |
35 | | #include <openbabel/alias.h> |
36 | | |
37 | | using namespace std; |
38 | | |
39 | | namespace OpenBabel |
40 | | { |
41 | | |
42 | | /** \class OBGenericData generic.h <openbabel/generic.h> |
43 | | |
44 | | OBGenericData is an abstract base class which defines an interface for |
45 | | storage, retrieval, and indexing of arbitrary generic data. |
46 | | Subclasses of OBGenericData can be used to store custom data |
47 | | on a per-atom, per-bond, per-molecule, or per-residue basis. |
48 | | Open Babel currently supports a small subset of chemical functionality |
49 | | as OBGenericData types, which will expand over time to support additional |
50 | | interconversion (e.g., spectroscopy, dynamics, surfaces...) |
51 | | |
52 | | For more information on currently supported types, please see |
53 | | the developer wiki: |
54 | | http://openbabel.org/wiki/Generic_Data |
55 | | |
56 | | For your own custom data, either define a custom subclass using |
57 | | an id from the OBGenericDataType::CustomData0 to |
58 | | OBGenericDataType::CustomData15 slots, |
59 | | or store your data as a string and use OBPairData for key/value access. |
60 | | The latter is <strong>highly</strong> recommended for various text |
61 | | descriptors |
62 | | e.g., in QSAR, atom or bond labels, or other textual data. |
63 | | |
64 | | <strong>New in Open Babel, version 2.1</strong> |
65 | | is the template-based OBPairTemplate, |
66 | | which can be used to store arbitrary data types. There are predefined |
67 | | types OBPairInteger and OBPairFloatingPoint for storing integers and |
68 | | floating-point values without converting to a string representation. |
69 | | |
70 | | Also <strong>new</strong> is the "source" or "origin" of a data |
71 | | entry, enumerated by DataOrigin. This can be accessed by |
72 | | SetOrigin() and GetOrigin(), as well as via "filtering" methods |
73 | | in OBBase, allowing you to separate data read in from a file, |
74 | | added by a user, or assigned by Open Babel internally. |
75 | | |
76 | | While the library and import routines will set DataOrigin correctly, |
77 | | you should try to annotate data added by your code. Typically this would |
78 | | either be userAdded or external. The former refers to something the |
79 | | user requested as an annotation, while the latter refers to annotations |
80 | | your code adds automatically. |
81 | | |
82 | | Example code using OBGenericData: |
83 | | |
84 | | @code |
85 | | if (mol.HasData(OBGenericDataType::UnitCell)) |
86 | | { |
87 | | uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell); |
88 | | sprintf(buffer, |
89 | | "%10.5f%10.5f%10.5f%10.5f%10.5f%10.5f", |
90 | | uc->GetA(), uc->GetB(), uc->GetC(), |
91 | | uc->GetAlpha() , uc->GetBeta(), uc->GetGamma()); |
92 | | ofs << buffer << endl; |
93 | | } |
94 | | |
95 | | ... |
96 | | |
97 | | vector<OBGenericData*>::iterator k; |
98 | | vector<OBGenericData*> vdata = mol.GetData(); |
99 | | for (k = vdata.begin();k != vdata.end();++k) |
100 | | if ((*k)->GetDataType() == OBGenericDataType::PairData) |
101 | | { |
102 | | ofs << "> <" << (*k)->GetAttribute() << ">" << endl; |
103 | | ofs << ((OBPairData*)(*k))->GetValue() << endl << endl; |
104 | | } |
105 | | @endcode |
106 | | |
107 | | Similar code also works for OBGenericData stored in an OBAtom or |
108 | | OBBond or OBResidue. These examples show use of DataOrigin outside |
109 | | of the Open Babel library. |
110 | | |
111 | | @code |
112 | | string atomLabel; // e.g., from the user adding annotation to an atom |
113 | | if (!atom.HasData("UserLabel")) // stored textual data as an OBPairData |
114 | | { |
115 | | OBPairData *label = new OBPairData; |
116 | | label->SetAttribute("UserLabel"); |
117 | | label->SetValue(atomLabel); |
118 | | label->SetOrigin(userInput); // set by user, not by Open Babel |
119 | | |
120 | | atom.SetData(label); |
121 | | } |
122 | | |
123 | | ... |
124 | | |
125 | | if (bond.HasData("DisplayType")) // e.g. in a visualization tool |
126 | | { |
127 | | OBPairData *display = dynamic_cast<OBPairData *> bond.GetData("DisplayType"); |
128 | | if (display->GetValue() == "wireframe") |
129 | | { |
130 | | ... // display a wireframe view |
131 | | } |
132 | | } |
133 | | @endcode |
134 | | |
135 | | When designing a class derived from OBGenericData you must add a |
136 | | Clone() function. For classes used with OBMol this is used when |
137 | | an OBMol object is copied. If your class member variables contain |
138 | | pointers to atoms or bonds then it will be necessary to ensure |
139 | | that these are updated in Clone() to refer to the new molecule. Without |
140 | | these and similar pointers it is more likely that the very simple |
141 | | clone function |
142 | | @code |
143 | | virtual OBGenericData* Clone(OBBase* parent) const |
144 | | {return new MyNewClass(*this);} |
145 | | @endcode |
146 | | and the compiler generated copy constructor would be sufficient. |
147 | | |
148 | | It is recommended that, if possible, OBGenericData classes do not |
149 | | store atom and bond pointers. Using atom and bond indices instead |
150 | | would allow the simple version of Clone() above. See |
151 | | OBRotameterData::Clone for an example of a more complicated version. |
152 | | For classes which are not intended to support copying, Clone() can |
153 | | return nullptr |
154 | | @code |
155 | | virtual OBGenericData* Clone(OBBase* parent) const |
156 | | {return nullptr;} |
157 | | @endcode |
158 | | Clone() is a pure virtual function so that you need to decide what |
159 | | kind of function you need and include it explicitly. |
160 | | **/ |
161 | | |
162 | | // |
163 | | //member functions for OBGenericData class |
164 | | // |
165 | | |
166 | | OBGenericData::OBGenericData(const std::string attr, const unsigned int type, |
167 | | const DataOrigin source): |
168 | 14.4M | _attr(attr), _type(type), _source(source) |
169 | 14.4M | { } |
170 | | |
171 | | /* Use default copy constructor and assignment operators |
172 | | OBGenericData::OBGenericData(const OBGenericData &src) |
173 | | { |
174 | | _type = src.GetDataType(); |
175 | | _attr = src.GetAttribute(); |
176 | | } |
177 | | |
178 | | |
179 | | OBGenericData& OBGenericData::operator = (const OBGenericData &src) |
180 | | { |
181 | | if(this == &src) |
182 | | return(*this); |
183 | | |
184 | | _type = src._type; |
185 | | _attr = src._attr; |
186 | | |
187 | | return(*this); |
188 | | } |
189 | | */ |
190 | | |
191 | | // |
192 | | //member functions for OBCommentData class |
193 | | // |
194 | | |
195 | | OBCommentData::OBCommentData(): |
196 | 0 | OBGenericData("Comment", OBGenericDataType::CommentData) |
197 | 0 | { } |
198 | | |
199 | | OBCommentData::OBCommentData(const OBCommentData &src) : |
200 | 0 | OBGenericData(src), _data(src._data) |
201 | 0 | { } |
202 | | |
203 | | // |
204 | | //member functions for OBExternalBond class |
205 | | // |
206 | | OBExternalBond::OBExternalBond(OBAtom *atom,OBBond *bond,int idx): |
207 | 237 | _idx(idx), _atom(atom), _bond(bond) |
208 | 237 | { } |
209 | | |
210 | | OBExternalBond::OBExternalBond(const OBExternalBond &src): |
211 | 402 | _idx(src._idx), _atom(src._atom), _bond(src._bond) |
212 | 402 | { } |
213 | | |
214 | | // |
215 | | //member functions for OBExternalBondData class |
216 | | // |
217 | | |
218 | | OBExternalBondData::OBExternalBondData(): |
219 | 110 | OBGenericData("ExternalBondData", OBGenericDataType::ExternalBondData, |
220 | 110 | perceived) |
221 | 110 | { } |
222 | | |
223 | | void OBExternalBondData::SetData(OBAtom *atom,OBBond *bond,int idx) |
224 | 237 | { |
225 | 237 | OBExternalBond xb(atom,bond,idx); |
226 | 237 | _vexbnd.push_back(xb); |
227 | 237 | } |
228 | | |
229 | | // |
230 | | //member functions for OBPairData class |
231 | | // |
232 | | |
233 | | OBPairData::OBPairData() : |
234 | 0 | OBGenericData("PairData", OBGenericDataType::PairData) |
235 | 0 | { } |
236 | | |
237 | | // |
238 | | //member functions for OBVirtualBond class |
239 | | // |
240 | | |
241 | | OBVirtualBond::OBVirtualBond(): |
242 | 0 | OBGenericData("VirtualBondData", OBGenericDataType::VirtualBondData, perceived), |
243 | 0 | _bgn(0), _end(0), _ord(0), _stereo(0) |
244 | 0 | { } |
245 | | |
246 | | OBVirtualBond::OBVirtualBond(unsigned int bgn, unsigned int end, unsigned int ord, int stereo): |
247 | 0 | OBGenericData("VirtualBondData", OBGenericDataType::VirtualBondData, perceived), |
248 | 0 | _bgn(bgn), _end(end), _ord(ord), _stereo(stereo) |
249 | 0 | { } |
250 | | |
251 | | // |
252 | | // member functions for OBUnitCell class |
253 | | // |
254 | | OBUnitCell::OBUnitCell(): |
255 | 0 | OBGenericData("UnitCell", OBGenericDataType::UnitCell), |
256 | 0 | _mOrtho(matrix3x3()), |
257 | 0 | _mOrient(matrix3x3()), |
258 | 0 | _offset(vector3()), |
259 | 0 | _spaceGroupName(""), _spaceGroup(nullptr), |
260 | 0 | _lattice(Undefined) |
261 | 0 | { } |
262 | | |
263 | | OBUnitCell::OBUnitCell(const OBUnitCell &src) : |
264 | 0 | OBGenericData("UnitCell", OBGenericDataType::UnitCell), |
265 | 0 | _mOrtho(src._mOrtho), |
266 | 0 | _mOrient(src._mOrient), |
267 | 0 | _offset(src._offset), |
268 | 0 | _spaceGroupName(src._spaceGroupName), _spaceGroup(src._spaceGroup), |
269 | 0 | _lattice(src._lattice) |
270 | 0 | { } |
271 | | |
272 | | OBUnitCell & OBUnitCell::operator=(const OBUnitCell &src) |
273 | 0 | { |
274 | 0 | if(this == &src) |
275 | 0 | return(*this); |
276 | | |
277 | 0 | _mOrtho = src._mOrtho; |
278 | 0 | _mOrient = src._mOrient; |
279 | 0 | _offset = src._offset; |
280 | |
|
281 | 0 | _spaceGroup = src._spaceGroup; |
282 | 0 | _spaceGroupName = src._spaceGroupName; |
283 | 0 | _lattice = src._lattice; |
284 | |
|
285 | 0 | return(*this); |
286 | 0 | } |
287 | | |
288 | | //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#calculateOrthogonalisationMatrix">blue-obelisk:calculateOrthogonalisationMatrix</a> |
289 | | void OBUnitCell::SetData(const double a, const double b, const double c, |
290 | | const double alpha, const double beta, const double gamma) |
291 | 0 | { |
292 | 0 | _mOrtho.FillOrth(alpha, beta, gamma, a, b, c); |
293 | 0 | _mOrient = matrix3x3(1); |
294 | 0 | _spaceGroup = nullptr; |
295 | 0 | _spaceGroupName = ""; |
296 | 0 | _lattice = OBUnitCell::Undefined; |
297 | 0 | } |
298 | | |
299 | | //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#calculateOrthogonalisationMatrix">blue-obelisk:calculateOrthogonalisationMatrix</a> |
300 | | void OBUnitCell::SetData(const vector3 v1, const vector3 v2, const vector3 v3) |
301 | 0 | { |
302 | 0 | matrix3x3 m (v1, v2, v3); |
303 | 0 | _mOrtho.FillOrth(vectorAngle(v2,v3), // alpha |
304 | 0 | vectorAngle(v1,v3), // beta |
305 | 0 | vectorAngle(v1,v2), // gamma |
306 | 0 | v1.length(), // a |
307 | 0 | v2.length(), // b |
308 | 0 | v3.length()); // c |
309 | 0 | _mOrient = m.transpose() * _mOrtho.inverse(); |
310 | 0 | _spaceGroup = nullptr; |
311 | 0 | _spaceGroupName = ""; |
312 | 0 | _lattice = OBUnitCell::Undefined; |
313 | 0 | } |
314 | | |
315 | | //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#calculateOrthogonalisationMatrix">blue-obelisk:calculateOrthogonalisationMatrix</a> |
316 | | void OBUnitCell::SetData(const matrix3x3 m) |
317 | 0 | { |
318 | 0 | SetData(m.GetRow(0), m.GetRow(1), m.GetRow(2)); |
319 | 0 | } |
320 | | |
321 | | void OBUnitCell::SetOffset(const vector3 v1) |
322 | 0 | { |
323 | 0 | _offset = v1; |
324 | 0 | } |
325 | | |
326 | | //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#convertNotionalIntoCartesianCoordinates">blue-obelisk:convertNotionalIntoCartesianCoordinates</a> |
327 | | vector<vector3> OBUnitCell::GetCellVectors() const |
328 | 0 | { |
329 | 0 | vector<vector3> v; |
330 | 0 | v.reserve(3); |
331 | |
|
332 | 0 | matrix3x3 m = GetCellMatrix(); |
333 | |
|
334 | 0 | v.push_back(m.GetRow(0)); |
335 | 0 | v.push_back(m.GetRow(1)); |
336 | 0 | v.push_back(m.GetRow(2)); |
337 | |
|
338 | 0 | return v; |
339 | 0 | } |
340 | | |
341 | | matrix3x3 OBUnitCell::GetCellMatrix() const |
342 | 0 | { |
343 | 0 | return (_mOrient * _mOrtho).transpose(); |
344 | 0 | } |
345 | | |
346 | | matrix3x3 OBUnitCell::GetOrthoMatrix() const |
347 | 0 | { |
348 | 0 | return _mOrtho; |
349 | 0 | } |
350 | | |
351 | | matrix3x3 OBUnitCell::GetOrientationMatrix() const |
352 | 0 | { |
353 | 0 | return _mOrient; |
354 | 0 | } |
355 | | |
356 | | matrix3x3 OBUnitCell::GetFractionalMatrix() const |
357 | 0 | { |
358 | 0 | return _mOrtho.inverse(); |
359 | 0 | } |
360 | | |
361 | | vector3 OBUnitCell::FractionalToCartesian(vector3 frac) const |
362 | 0 | { |
363 | 0 | return _mOrient * _mOrtho * frac + _offset; |
364 | 0 | } |
365 | | |
366 | | vector3 OBUnitCell::CartesianToFractional(vector3 cart) const |
367 | 0 | { |
368 | 0 | return _mOrtho.inverse() * _mOrient.inverse() * (cart - _offset); |
369 | 0 | } |
370 | | |
371 | | vector3 OBUnitCell::WrapCartesianCoordinate(vector3 cart) const |
372 | 0 | { |
373 | 0 | vector3 v = CartesianToFractional(cart); |
374 | 0 | v = WrapFractionalCoordinate(v); |
375 | 0 | return FractionalToCartesian(v); |
376 | 0 | } |
377 | | |
378 | | vector3 OBUnitCell::WrapFractionalCoordinate(vector3 frac) const |
379 | 0 | { |
380 | 0 | double x = fmod(frac.x(), 1); |
381 | 0 | double y = fmod(frac.y(), 1); |
382 | 0 | double z = fmod(frac.z(), 1); |
383 | 0 | if (x < 0) x += 1; |
384 | 0 | if (y < 0) y += 1; |
385 | 0 | if (z < 0) z += 1; |
386 | |
|
387 | 0 | #define LIMIT 0.999999 |
388 | 0 | if (x > LIMIT) |
389 | 0 | x -= 1; |
390 | 0 | if (y > LIMIT) |
391 | 0 | y -= 1; |
392 | 0 | if (z > LIMIT) |
393 | 0 | z -= 1; |
394 | 0 | #undef LIMIT |
395 | | |
396 | | // Fuzzy logic from Francois-Xavier |
397 | 0 | #define EPSILON 1.0e-6 |
398 | 0 | if (x > 1 - EPSILON || x < EPSILON) |
399 | 0 | x = 0.0; |
400 | 0 | if (y > 1 - EPSILON || y < EPSILON) |
401 | 0 | y = 0.0; |
402 | 0 | if (z > 1 - EPSILON || z < EPSILON) |
403 | 0 | z = 0.0; |
404 | 0 | #undef EPSILON |
405 | |
|
406 | 0 | return vector3(x, y, z); |
407 | 0 | } |
408 | | |
409 | | vector3 OBUnitCell::UnwrapCartesianNear(vector3 new_loc, vector3 ref_loc) const |
410 | 0 | { |
411 | 0 | vector3 bond_dir = MinimumImageCartesian(new_loc - ref_loc); |
412 | 0 | return ref_loc + bond_dir; |
413 | 0 | } |
414 | | |
415 | | vector3 OBUnitCell::UnwrapFractionalNear(vector3 new_loc, vector3 ref_loc) const |
416 | 0 | { |
417 | 0 | vector3 bond_dir = MinimumImageFractional(new_loc - ref_loc); |
418 | 0 | return ref_loc + bond_dir; |
419 | 0 | } |
420 | | |
421 | | vector3 OBUnitCell::MinimumImageCartesian(vector3 cart) const |
422 | 0 | { |
423 | 0 | vector3 frac = CartesianToFractional(cart); |
424 | 0 | frac = MinimumImageFractional(frac); |
425 | 0 | return FractionalToCartesian(frac); |
426 | 0 | } |
427 | | |
428 | | vector3 OBUnitCell::MinimumImageFractional(vector3 frac) const |
429 | 0 | { |
430 | 0 | double x = frac.x() - round(frac.x()); |
431 | 0 | double y = frac.y() - round(frac.y()); |
432 | 0 | double z = frac.z() - round(frac.z()); |
433 | 0 | return vector3(x, y, z); |
434 | 0 | } |
435 | | |
436 | | OBUnitCell::LatticeType OBUnitCell::GetLatticeType( int spacegroup ) const |
437 | 0 | { |
438 | | // 1-2 Triclinic |
439 | | // 3-15 Monoclinic |
440 | | // 16-74 Orthorhombic |
441 | | // 75-142 Tetragonal |
442 | | // 143-167 Rhombohedral |
443 | | // 168-194 Hexagonal |
444 | | // 195-230 Cubic |
445 | |
|
446 | 0 | if ( spacegroup == 0 && _spaceGroup) |
447 | 0 | spacegroup = _spaceGroup->GetId(); |
448 | |
|
449 | 0 | if ( spacegroup <= 0 ) |
450 | 0 | return OBUnitCell::Undefined; |
451 | | |
452 | 0 | else if ( spacegroup == 1 || |
453 | 0 | spacegroup == 2 ) |
454 | 0 | return OBUnitCell::Triclinic; |
455 | | |
456 | 0 | else if ( spacegroup >= 3 && |
457 | 0 | spacegroup <= 15 ) |
458 | 0 | return OBUnitCell::Monoclinic; |
459 | | |
460 | 0 | else if ( spacegroup >= 16 && |
461 | 0 | spacegroup <= 74 ) |
462 | 0 | return OBUnitCell::Orthorhombic; |
463 | | |
464 | 0 | else if ( spacegroup >= 75 && |
465 | 0 | spacegroup <= 142 ) |
466 | 0 | return OBUnitCell::Tetragonal; |
467 | | |
468 | 0 | else if ( spacegroup >= 143 && |
469 | 0 | spacegroup <= 167 ) |
470 | 0 | return OBUnitCell::Rhombohedral; |
471 | | |
472 | 0 | else if ( spacegroup >= 168 && |
473 | 0 | spacegroup <= 194 ) |
474 | 0 | return OBUnitCell::Hexagonal; |
475 | | |
476 | 0 | else if ( spacegroup >= 195 && |
477 | 0 | spacegroup <= 230 ) |
478 | 0 | return OBUnitCell::Cubic; |
479 | | |
480 | | //just to be extra sure |
481 | 0 | else // ( spacegroup > 230 ) |
482 | 0 | return OBUnitCell::Undefined; |
483 | 0 | } |
484 | | |
485 | | OBUnitCell::LatticeType OBUnitCell::GetLatticeType() const |
486 | 0 | { |
487 | 0 | if (_lattice != Undefined) |
488 | 0 | return _lattice; |
489 | 0 | else if (_spaceGroup != nullptr) |
490 | 0 | return GetLatticeType(_spaceGroup->GetId()); |
491 | | |
492 | 0 | double a = GetA(); |
493 | 0 | double b = GetB(); |
494 | 0 | double c = GetC(); |
495 | 0 | double alpha = GetAlpha(); |
496 | 0 | double beta = GetBeta(); |
497 | 0 | double gamma = GetGamma(); |
498 | |
|
499 | 0 | unsigned int rightAngles = 0; |
500 | 0 | if (IsApprox(alpha, 90.0, 1.0e-3)) rightAngles++; |
501 | 0 | if (IsApprox(beta, 90.0, 1.0e-3)) rightAngles++; |
502 | 0 | if (IsApprox(gamma, 90.0, 1.0e-3)) rightAngles++; |
503 | | |
504 | | // recast cache member "_lattice" as mutable |
505 | 0 | OBUnitCell::LatticeType *lattice = |
506 | 0 | const_cast<OBUnitCell::LatticeType*>(&_lattice); |
507 | |
|
508 | 0 | switch (rightAngles) |
509 | 0 | { |
510 | 0 | case 3: |
511 | 0 | if (IsApprox(a, b, 1.0e-4) && IsApprox(b, c, 1.0e-4)) |
512 | 0 | *lattice = Cubic; |
513 | 0 | else if (IsApprox(a, b, 1.0e-4) || IsApprox(b, c, 1.0e-4)) |
514 | 0 | *lattice = Tetragonal; |
515 | 0 | else |
516 | 0 | *lattice = Orthorhombic; |
517 | 0 | break; |
518 | 0 | case 2: |
519 | 0 | if ( (IsApprox(alpha, 120.0, 1.0e-3) |
520 | 0 | || IsApprox(beta, 120.0, 1.0e-3) |
521 | 0 | || IsApprox(gamma, 120.0f, 1.0e-3)) |
522 | 0 | && (IsApprox(a, b, 1.0e-4) || IsApprox(b, c, 1.0e-4)) ) |
523 | 0 | *lattice = Hexagonal; |
524 | 0 | else |
525 | 0 | *lattice = Monoclinic; |
526 | 0 | break; |
527 | 0 | default: |
528 | 0 | if (IsApprox(a, b, 1.0e-4) && IsApprox(b, c, 1.0e-4)) |
529 | 0 | *lattice = Rhombohedral; |
530 | 0 | else |
531 | 0 | *lattice = Triclinic; |
532 | 0 | } |
533 | | |
534 | 0 | return *lattice; |
535 | 0 | } |
536 | | |
537 | | int OBUnitCell::GetSpaceGroupNumber( std::string name) const |
538 | 0 | { |
539 | 0 | static const char * const spacegroups[] = { |
540 | 0 | "P1", "P-1", "P2", "P2(1)", "C2", "Pm", "Pc", "Cm", "Cc", "P2/m", |
541 | 0 | "P2(1)/m", "C2/m", "P2/c", "P2(1)/c", "C2/c", "P222", "P222(1)", |
542 | 0 | "P2(1)2(1)2", "P2(1)2(1)2(1)", "C222(1)", "C222", "F222", "I222", |
543 | 0 | "I2(1)2(1)2(1)", "Pmm2", "Pmc2(1)", "Pcc2", "Pma2", "Pca2(1)", "Pnc2", |
544 | 0 | "Pmn2(1)", "Pba2", "Pna2(1)", "Pnn2", "Cmm2", "Cmc2(1)", "Ccc2", "Amm2", |
545 | 0 | "Abm2", "Ama2", "Aba2", "Fmm2", "Fdd2", "Imm2", "Iba2", "Ima2", "Pmmm", |
546 | 0 | "Pnnn", "Pccm", "Pban", "Pmma", "Pnna", "Pmna", "Pcca", "Pbam", "Pccn", |
547 | 0 | "Pbcm", "Pnnm", "Pmmn", "Pbcn", "Pbca", "Pnma", "Cmcm", "Cmca", "Cmmm", |
548 | 0 | "Cccm", "Cmma", "Ccca", "Fmmm", "Fddd", "Immm", "Ibam", "Ibca", "Imma", |
549 | 0 | "P4", "P4(1)", "P4(2)", "P4(3)", "I4", "I4(1)", "P-4", "I-4", "P4/m", |
550 | 0 | "P4(2)/m", "P4/n", "P4(2)/n", "I4/m", "I4(1)/a", "P422", "P42(1)2", |
551 | 0 | "P4(1)22", "P4(1)2(1)2", "P4(2)22", "P4(2)2(1)2", "P4(3)22", "P4(3)2(1)2", |
552 | 0 | "I422", "I4(1)22", "P4mm", "P4bm", "P4(2)cm", "P4(2)nm", "P4cc", "P4nc", |
553 | 0 | "P4(2)mc", "P4(2)bc", "I4mm", "I4cm", "I4(1)md", "I4(1)cd", "P-42m", |
554 | 0 | "P-42c", "P-42(1)m", "P-42(1)c", "P-4m2", "P-4c2", "P-4b2", "P-4n2", |
555 | 0 | "I-4m2", "I-4c2", "I-42m", "I-42d", "P4/mmm", "P4/mcc", "P4/nbm", |
556 | 0 | "P4/nnc", "P4/mbm", "P4/mnc", "P4/nmm", "P4/ncc", "P4(2)/mmc", |
557 | 0 | "P4(2)/mcm", "P4(2)/nbc", "P4(2)/nnm", "P4(2)/mbc", "P4(2)/mnm", |
558 | 0 | "P4(2)/nmc", "P4(2)/ncm", "I4/mmm", "I4/mcm", "I4(1)/amd", "I4(1)/acd", |
559 | 0 | "P3", "P3(1)", "P3(2)", "R3", "P-3", "R-3", "P312", "P321", "P3(1)12", |
560 | 0 | "P3(1)21", "P3(2)12", "P3(2)21", "R32", "P3m1", "P31m", "P3c1", "P31c", |
561 | 0 | "R3m", "R3c", "P-31m", "P-31c", "P-3m1", "P-3c1", "R-3m", "R-3c", "P6", |
562 | 0 | "P6(1)", "P6(5)", "P6(2)", "P6(4)", "P6(3)", "P-6", "P6/m", "P6(3)/m", |
563 | 0 | "P622", "P6(1)22", "P6(5)22", "P6(2)22", "P6(4)22", "P6(3)22", "P6mm", |
564 | 0 | "P6cc", "P6(3)cm", "P6(3)mc", "P-6m2", "P-6c2", "P-62m", "P-62c", |
565 | 0 | "P6/mmm", "P6/mcc", "P6(3)/mcm", "P6(3)/mmc", "P23", "F23", "I23", |
566 | 0 | "P2(1)3", "I2(1)3", "Pm-3", "Pn-3", "Fm-3", "Fd-3", "Im-3", "Pa-3", |
567 | 0 | "Ia-3", "P432", "P4(2)32", "F432", "F4(1)32", "I432", "P4(3)32", |
568 | 0 | "P4(1)32", "I4(1)32", "P-43m", "F4-3m", "I-43m", "P-43n", "F-43c", |
569 | 0 | "I-43d", "Pm-3m", "Pn-3n", "Pm-3n", "Pn-3m", "Fm-3m", "Fm-3c", |
570 | 0 | "Fd-3m", "Fd-3c", "Im-3m", "Ia-3d" |
571 | 0 | }; |
572 | |
|
573 | 0 | if (name.length () == 0) |
574 | 0 | { |
575 | 0 | if (_spaceGroup != nullptr) |
576 | 0 | return _spaceGroup->GetId(); |
577 | 0 | else |
578 | 0 | name = _spaceGroupName; |
579 | 0 | } |
580 | 0 | static const int numStrings = sizeof( spacegroups ) / sizeof( spacegroups[0] ); |
581 | 0 | for ( int i = 0; i < numStrings; ++i ) { |
582 | 0 | if (name == spacegroups[i] ) { |
583 | 0 | return i+1; |
584 | 0 | } |
585 | 0 | } |
586 | 0 | return 0; //presumably never reached |
587 | 0 | } |
588 | | |
589 | | // Whether two points (given in fractional coordinates) are close enough |
590 | | // to be considered duplicates. |
591 | | bool areDuplicateAtoms (vector3 v1, vector3 v2) |
592 | 0 | { |
593 | 0 | vector3 dr = v2 - v1; |
594 | 0 | if (dr.x() < -0.5) |
595 | 0 | dr.SetX(dr.x() + 1); |
596 | 0 | if (dr.x() > 0.5) |
597 | 0 | dr.SetX(dr.x() - 1); |
598 | 0 | if (dr.y() < -0.5) |
599 | 0 | dr.SetY(dr.y() + 1); |
600 | 0 | if (dr.y() > 0.5) |
601 | 0 | dr.SetY(dr.y() - 1); |
602 | 0 | if (dr.z() < -0.5) |
603 | 0 | dr.SetZ(dr.z() + 1); |
604 | 0 | if (dr.z() > 0.5) |
605 | 0 | dr.SetZ(dr.z() - 1); |
606 | |
|
607 | 0 | return (dr.length_2() < 1e-6); |
608 | 0 | } |
609 | | |
610 | | void OBUnitCell::FillUnitCell(OBMol *mol) |
611 | 0 | { |
612 | 0 | const SpaceGroup *sg = GetSpaceGroup(); // the actual space group and transformations for this unit cell |
613 | |
|
614 | 0 | if (sg == nullptr) |
615 | 0 | return ; |
616 | | |
617 | | // For each atom, we loop through: convert the coords back to inverse space, apply the transformations and create new atoms |
618 | 0 | vector3 baseV, uniqueV, updatedCoordinate; |
619 | 0 | list<vector3> transformedVectors; // list of symmetry-defined copies of the atom |
620 | 0 | list<vector3>::iterator transformIter; |
621 | 0 | list<OBAtom*>::iterator deleteIter, atomIter; |
622 | 0 | OBAtom *newAtom; |
623 | 0 | list<OBAtom*> atoms, atomsToDelete; |
624 | 0 | char hash[22]; |
625 | 0 | set<string> coordinateSet; |
626 | | |
627 | | // Check original mol for duplicates |
628 | 0 | FOR_ATOMS_OF_MOL(atom, *mol) { |
629 | 0 | baseV = atom->GetVector(); |
630 | 0 | baseV = CartesianToFractional(baseV); |
631 | 0 | baseV = WrapFractionalCoordinate(baseV); |
632 | 0 | snprintf(hash, 22, "%03d,%.3f,%.3f,%.3f", atom->GetAtomicNum(), baseV.x(), baseV.y(), baseV.z()); |
633 | 0 | if (coordinateSet.insert(hash).second) { // True if new entry |
634 | 0 | atoms.push_back(&(*atom)); |
635 | 0 | } else { |
636 | 0 | atomsToDelete.push_back(&(*atom)); |
637 | 0 | } |
638 | 0 | } |
639 | 0 | for (deleteIter = atomsToDelete.begin(); deleteIter != atomsToDelete.end(); ++deleteIter) { |
640 | 0 | mol->DeleteAtom(*deleteIter); |
641 | 0 | } |
642 | | |
643 | | // Cross-check all transformations for duplicity |
644 | 0 | for (atomIter = atoms.begin(); atomIter != atoms.end(); ++atomIter) { |
645 | 0 | uniqueV = (*atomIter)->GetVector(); |
646 | 0 | uniqueV = CartesianToFractional(uniqueV); |
647 | 0 | uniqueV = WrapFractionalCoordinate(uniqueV); |
648 | |
|
649 | 0 | transformedVectors = sg->Transform(uniqueV); |
650 | 0 | for (transformIter = transformedVectors.begin(); |
651 | 0 | transformIter != transformedVectors.end(); ++transformIter) { |
652 | 0 | updatedCoordinate = WrapFractionalCoordinate(*transformIter); |
653 | | |
654 | | // Check if the transformed coordinate is a duplicate of an atom |
655 | 0 | snprintf(hash, 22, "%03d,%.3f,%.3f,%.3f", (*atomIter)->GetAtomicNum(), updatedCoordinate.x(), |
656 | 0 | updatedCoordinate.y(), updatedCoordinate.z()); |
657 | 0 | if (coordinateSet.insert(hash).second) { |
658 | 0 | newAtom = mol->NewAtom(); |
659 | 0 | newAtom->Duplicate(*atomIter); |
660 | 0 | newAtom->SetVector(FractionalToCartesian(updatedCoordinate)); |
661 | 0 | } |
662 | 0 | } // end loop of transformed atoms |
663 | 0 | } // end loop of atoms |
664 | 0 | SetSpaceGroup(1); // We've now applied the symmetry, so we should act like a P1 unit cell |
665 | 0 | } |
666 | | |
667 | | /// @todo Remove nonconst overloads in OBUnitCell on next version bump. |
668 | | #define OBUNITCELL_CALL_CONST_OVERLOAD(_type, _name) \ |
669 | | _type OBUnitCell::_name() \ |
670 | 0 | { \ |
671 | 0 | return const_cast<const OBUnitCell*>(this)->_name(); \ |
672 | 0 | } Unexecuted instantiation: OpenBabel::OBUnitCell::GetA() Unexecuted instantiation: OpenBabel::OBUnitCell::GetB() Unexecuted instantiation: OpenBabel::OBUnitCell::GetC() Unexecuted instantiation: OpenBabel::OBUnitCell::GetAlpha() Unexecuted instantiation: OpenBabel::OBUnitCell::GetBeta() Unexecuted instantiation: OpenBabel::OBUnitCell::GetGamma() Unexecuted instantiation: OpenBabel::OBUnitCell::GetOffset() Unexecuted instantiation: OpenBabel::OBUnitCell::GetLatticeType() Unexecuted instantiation: OpenBabel::OBUnitCell::GetCellVectors() Unexecuted instantiation: OpenBabel::OBUnitCell::GetCellMatrix() Unexecuted instantiation: OpenBabel::OBUnitCell::GetOrthoMatrix() Unexecuted instantiation: OpenBabel::OBUnitCell::GetOrientationMatrix() Unexecuted instantiation: OpenBabel::OBUnitCell::GetFractionalMatrix() Unexecuted instantiation: OpenBabel::OBUnitCell::GetCellVolume() |
673 | | #define OBUNITCELL_CALL_CONST_OVERLOAD_ARG(_type, _name, _argsig) \ |
674 | | _type OBUnitCell::_name( _argsig arg1 ) \ |
675 | 0 | { \ |
676 | 0 | return const_cast<const OBUnitCell*>(this)->_name(arg1); \ |
677 | 0 | } Unexecuted instantiation: OpenBabel::OBUnitCell::GetLatticeType(int) Unexecuted instantiation: OpenBabel::OBUnitCell::FractionalToCartesian(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::CartesianToFractional(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::WrapCartesianCoordinate(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::WrapFractionalCoordinate(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::MinimumImageCartesian(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::MinimumImageFractional(OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::GetSpaceGroupNumber(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) |
678 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetA); |
679 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetB); |
680 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetC); |
681 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetAlpha); |
682 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetBeta); |
683 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetGamma); |
684 | | OBUNITCELL_CALL_CONST_OVERLOAD(vector3, GetOffset); |
685 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(OBUnitCell::LatticeType, |
686 | | GetLatticeType, int); |
687 | | OBUNITCELL_CALL_CONST_OVERLOAD(OBUnitCell::LatticeType, GetLatticeType); |
688 | | OBUNITCELL_CALL_CONST_OVERLOAD(std::vector<vector3>, GetCellVectors); |
689 | | OBUNITCELL_CALL_CONST_OVERLOAD(matrix3x3, GetCellMatrix ); |
690 | | OBUNITCELL_CALL_CONST_OVERLOAD(matrix3x3, GetOrthoMatrix ); |
691 | | OBUNITCELL_CALL_CONST_OVERLOAD(matrix3x3, GetOrientationMatrix ); |
692 | | OBUNITCELL_CALL_CONST_OVERLOAD(matrix3x3, GetFractionalMatrix ); |
693 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, FractionalToCartesian, vector3); |
694 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, CartesianToFractional, vector3); |
695 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, WrapCartesianCoordinate, vector3); |
696 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, WrapFractionalCoordinate, vector3); |
697 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, MinimumImageCartesian, vector3); |
698 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(vector3, MinimumImageFractional, vector3); |
699 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG(int, GetSpaceGroupNumber, std::string); |
700 | | OBUNITCELL_CALL_CONST_OVERLOAD(double, GetCellVolume); |
701 | | // Based on OBUNITCELL_CALL_CONST_OVERLOAD_ARG above |
702 | | #define OBUNITCELL_CALL_CONST_OVERLOAD_ARG2(_type, _name, _argsig, _argsig2) \ |
703 | | _type OBUnitCell::_name( _argsig arg1, _argsig2 arg2 ) \ |
704 | 0 | { \ |
705 | 0 | return const_cast<const OBUnitCell*>(this)->_name(arg1, arg2); \ |
706 | 0 | } Unexecuted instantiation: OpenBabel::OBUnitCell::UnwrapCartesianNear(OpenBabel::vector3, OpenBabel::vector3) Unexecuted instantiation: OpenBabel::OBUnitCell::UnwrapFractionalNear(OpenBabel::vector3, OpenBabel::vector3) |
707 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG2(vector3, UnwrapCartesianNear, vector3, vector3); |
708 | | OBUNITCELL_CALL_CONST_OVERLOAD_ARG2(vector3, UnwrapFractionalNear, vector3, vector3); |
709 | | |
710 | | double OBUnitCell::GetA() const |
711 | 0 | { |
712 | 0 | return _mOrtho.GetColumn(0).length(); |
713 | 0 | } |
714 | | |
715 | | double OBUnitCell::GetB() const |
716 | 0 | { |
717 | 0 | return _mOrtho.GetColumn(1).length(); |
718 | 0 | } |
719 | | |
720 | | double OBUnitCell::GetC() const |
721 | 0 | { |
722 | 0 | return _mOrtho.GetColumn(2).length(); |
723 | 0 | } |
724 | | |
725 | | double OBUnitCell::GetAlpha() const |
726 | 0 | { |
727 | 0 | return vectorAngle(_mOrtho.GetColumn(1), _mOrtho.GetColumn(2)); |
728 | 0 | } |
729 | | |
730 | | double OBUnitCell::GetBeta() const |
731 | 0 | { |
732 | 0 | return vectorAngle(_mOrtho.GetColumn(0), _mOrtho.GetColumn(2)); |
733 | 0 | } |
734 | | |
735 | | double OBUnitCell::GetGamma() const |
736 | 0 | { |
737 | 0 | return vectorAngle(_mOrtho.GetColumn(0), _mOrtho.GetColumn(1)); |
738 | 0 | } |
739 | | |
740 | | vector3 OBUnitCell::GetOffset() const |
741 | 0 | { |
742 | 0 | return _offset; |
743 | 0 | } |
744 | | |
745 | | double OBUnitCell::GetCellVolume() const |
746 | 0 | { |
747 | 0 | return fabs(GetCellMatrix().determinant()); |
748 | 0 | } |
749 | | |
750 | | // |
751 | | // member functions for OBSymmetryData class |
752 | | // |
753 | | OBSymmetryData::OBSymmetryData(): |
754 | 0 | OBGenericData("Symmetry", OBGenericDataType::SymmetryData) |
755 | 0 | { } |
756 | | |
757 | | OBSymmetryData::OBSymmetryData(const OBSymmetryData &src) : |
758 | 0 | OBGenericData(src._attr, src._type, src._source), |
759 | 0 | _spaceGroup(src._spaceGroup), |
760 | 0 | _pointGroup(src._pointGroup) |
761 | 0 | { } |
762 | | |
763 | | OBSymmetryData & OBSymmetryData::operator=(const OBSymmetryData &src) |
764 | 0 | { |
765 | 0 | if(this == &src) |
766 | 0 | return(*this); |
767 | | |
768 | 0 | _pointGroup = src._pointGroup; |
769 | 0 | _spaceGroup = src._spaceGroup; |
770 | 0 | _source = src._source; |
771 | |
|
772 | 0 | return(*this); |
773 | 0 | } |
774 | | |
775 | | OBConformerData::OBConformerData() : |
776 | 0 | OBGenericData("Conformers", OBGenericDataType::ConformerData) |
777 | 0 | { } |
778 | | |
779 | | OBConformerData::OBConformerData(const OBConformerData &src) : |
780 | 0 | OBGenericData("Conformers", OBGenericDataType::ConformerData), |
781 | 0 | _vDimension(src._vDimension), |
782 | 0 | _vEnergies(src._vEnergies), _vForces(src._vForces), |
783 | 0 | _vVelocity(src._vVelocity), _vDisplace(src._vDisplace), |
784 | 0 | _vData(src._vData) |
785 | 0 | { } |
786 | | |
787 | | OBConformerData & OBConformerData::operator=(const OBConformerData &src) |
788 | 0 | { |
789 | 0 | if(this == &src) |
790 | 0 | return(*this); |
791 | | |
792 | 0 | _source = src._source; |
793 | |
|
794 | 0 | _vDimension = src._vDimension; |
795 | 0 | _vEnergies = src._vEnergies; |
796 | 0 | _vForces = src._vForces; |
797 | 0 | _vVelocity = src._vVelocity; |
798 | 0 | _vDisplace = src._vDisplace; |
799 | 0 | _vData = src._vData; |
800 | |
|
801 | 0 | return(*this); |
802 | 0 | } |
803 | | |
804 | | // |
805 | | //member functions for OBRingData class |
806 | | // |
807 | | |
808 | | OBRingData::OBRingData() : |
809 | 4.89k | OBGenericData("RingData", OBGenericDataType::RingData) |
810 | 4.89k | { |
811 | 4.89k | _vr.clear(); |
812 | 4.89k | } |
813 | | |
814 | | /*! |
815 | | **\brief OBRingData copy constructor |
816 | | **\param src reference to original OBRingData object (rhs) |
817 | | */ |
818 | | OBRingData::OBRingData(const OBRingData &src) |
819 | 0 | : OBGenericData(src), //chain to base class |
820 | 0 | _vr(src._vr) //chain to member classes |
821 | 0 | { |
822 | | //no other memeber data |
823 | | //memory management |
824 | |
|
825 | 0 | vector<OBRing*>::iterator ring; |
826 | |
|
827 | 0 | for(ring = _vr.begin();ring != _vr.end();++ring) |
828 | 0 | { |
829 | 0 | OBRing *newring = new OBRing; |
830 | 0 | (*newring) = (**ring); //copy data to new object |
831 | 0 | (*ring) = newring; //repoint new pointer to new copy of data |
832 | 0 | } |
833 | 0 | } |
834 | | |
835 | | OBRingData::~OBRingData() |
836 | 4.89k | { |
837 | 4.89k | vector<OBRing*>::iterator ring; |
838 | 154k | for (ring = _vr.begin();ring != _vr.end();++ring) |
839 | 149k | { |
840 | 149k | delete *ring; |
841 | 149k | } |
842 | 4.89k | } |
843 | | |
844 | | /*! |
845 | | **\brief OBRingData assignment operator |
846 | | **\param src reference to original OBRingData object (rhs) |
847 | | **\return reference to changed OBRingData object (lhs) |
848 | | */ |
849 | | OBRingData& OBRingData::operator =(const OBRingData &src) |
850 | 0 | { |
851 | | //on identity, return |
852 | 0 | if(this == &src) |
853 | 0 | return(*this); |
854 | | |
855 | | //chain to base class |
856 | 0 | OBGenericData::operator =(src); |
857 | | |
858 | | //member data |
859 | | |
860 | | //memory management |
861 | 0 | vector<OBRing*>::iterator ring; |
862 | 0 | for(ring = _vr.begin();ring != _vr.end();++ring) |
863 | 0 | { |
864 | 0 | delete &*ring; //deallocate old rings to prevent memory leak |
865 | 0 | } |
866 | |
|
867 | 0 | _vr.clear(); |
868 | 0 | _vr = src._vr; //copy vector properties |
869 | |
|
870 | 0 | for(ring = _vr.begin();ring != _vr.end();++ring) |
871 | 0 | { |
872 | 0 | if(*ring == 0) |
873 | 0 | continue; |
874 | | |
875 | | //allocate and copy ring data |
876 | 0 | OBRing *newring = new OBRing; |
877 | 0 | (*newring) = (**ring); |
878 | 0 | (*ring) = newring; //redirect pointer |
879 | 0 | } |
880 | 0 | return(*this); |
881 | 0 | } |
882 | | |
883 | | OBRing *OBRingData::BeginRing(std::vector<OBRing*>::iterator &i) |
884 | 0 | { |
885 | 0 | i = _vr.begin(); |
886 | 0 | return i == _vr.end() ? nullptr : (OBRing*)*i; |
887 | 0 | } |
888 | | |
889 | | OBRing *OBRingData::NextRing(std::vector<OBRing*>::iterator &i) |
890 | 0 | { |
891 | 0 | ++i; |
892 | 0 | return i == _vr.end() ? nullptr : (OBRing*)*i; |
893 | 0 | } |
894 | | |
895 | | // |
896 | | //member functions for OBAngle class - stores all angles |
897 | | // |
898 | | |
899 | | /*! |
900 | | **\brief Angle default constructor |
901 | | */ |
902 | | OBAngle::OBAngle(): |
903 | 0 | _vertex(nullptr), _termini(nullptr, nullptr), _radians(0.0) |
904 | 0 | { } |
905 | | |
906 | | /*! |
907 | | **\brief Angle constructor |
908 | | */ |
909 | | OBAngle::OBAngle(OBAtom *vertex,OBAtom *a,OBAtom *b): |
910 | 0 | _vertex(vertex), _termini(a, b) |
911 | 0 | { |
912 | 0 | SortByIndex(); |
913 | 0 | } |
914 | | |
915 | | /*! |
916 | | **\brief OBAngle copy constructor |
917 | | */ |
918 | | OBAngle::OBAngle(const OBAngle &src): |
919 | 0 | _vertex(src._vertex), _termini(src._termini), _radians(src._radians) |
920 | 0 | { } |
921 | | |
922 | | /*! |
923 | | **\brief OBAngle assignment operator |
924 | | */ |
925 | | OBAngle& OBAngle::operator = (const OBAngle &src) |
926 | 0 | { |
927 | 0 | if (this == &src) |
928 | 0 | return(*this); |
929 | | |
930 | 0 | _vertex = src._vertex; |
931 | 0 | _termini.first = src._termini.first; |
932 | 0 | _termini.second = src._termini.second; |
933 | 0 | _radians = src._radians; |
934 | |
|
935 | 0 | return(*this); |
936 | 0 | } |
937 | | |
938 | | /*! |
939 | | **\brief Return OBAngle to its original state |
940 | | */ |
941 | | void OBAngle::Clear() |
942 | 0 | { |
943 | 0 | _vertex = nullptr; |
944 | 0 | _termini.first = 0; |
945 | 0 | _termini.second = 0; |
946 | 0 | _radians = 0.0; |
947 | 0 | return; |
948 | 0 | } |
949 | | |
950 | | /*! |
951 | | **\brief Sets the 3 atoms in the angle |
952 | | ** Parameters are pointers to each OBAtom |
953 | | */ |
954 | | void OBAngle::SetAtoms(OBAtom *vertex,OBAtom *a,OBAtom *b) |
955 | 0 | { |
956 | 0 | _vertex = vertex; |
957 | 0 | _termini.first = a; |
958 | 0 | _termini.second = b; |
959 | 0 | SortByIndex(); |
960 | 0 | return; |
961 | 0 | } |
962 | | |
963 | | /*! |
964 | | **\brief Sets the 3 atoms in the angle |
965 | | **\param atoms a triple of OBAtom pointers, the first must be the vertex |
966 | | */ |
967 | | void OBAngle::SetAtoms(triple<OBAtom*,OBAtom*,OBAtom*> &atoms) |
968 | 0 | { |
969 | 0 | _vertex = atoms.first; |
970 | 0 | _termini.first = atoms.second; |
971 | 0 | _termini.second = atoms.third; |
972 | 0 | SortByIndex(); |
973 | 0 | return; |
974 | 0 | } |
975 | | |
976 | | /*! |
977 | | **\brief Retrieves the 3 atom pointer for the angle (vertex first) |
978 | | **\return triple of OBAtom pointers |
979 | | */ |
980 | | triple<OBAtom*,OBAtom*,OBAtom*> OBAngle::GetAtoms() |
981 | 0 | { |
982 | 0 | triple<OBAtom*,OBAtom*,OBAtom*> atoms; |
983 | 0 | atoms.first = _vertex; |
984 | 0 | atoms.second = _termini.first; |
985 | 0 | atoms.third = _termini.second; |
986 | 0 | return(atoms); |
987 | 0 | } |
988 | | |
989 | | /*! |
990 | | **\brief sorts atoms in angle by order of indices |
991 | | */ |
992 | | void OBAngle::SortByIndex() |
993 | 0 | { |
994 | 0 | OBAtom *tmp; |
995 | |
|
996 | 0 | if(_termini.first->GetIdx() > _termini.second->GetIdx()) |
997 | 0 | { |
998 | 0 | tmp = _termini.first; |
999 | 0 | _termini.first = _termini.second; |
1000 | 0 | _termini.second = tmp; |
1001 | 0 | } |
1002 | 0 | } |
1003 | | |
1004 | | /*! |
1005 | | **\brief OBAngle equality operator, is same angle, NOT same value |
1006 | | **\return boolean equality |
1007 | | */ |
1008 | | bool OBAngle::operator ==(const OBAngle &other) |
1009 | 0 | { |
1010 | 0 | return ((_vertex == other._vertex) && |
1011 | 0 | (_termini.first == other._termini.first) && |
1012 | 0 | (_termini.second == other._termini.second)); |
1013 | 0 | } |
1014 | | |
1015 | | // |
1016 | | //member functions for OBAngleData class - stores OBAngle set |
1017 | | // |
1018 | | |
1019 | | /*! |
1020 | | **\brief OBAngleData constructor |
1021 | | */ |
1022 | | OBAngleData::OBAngleData() |
1023 | 0 | : OBGenericData("AngleData", OBGenericDataType::AngleData) |
1024 | 0 | { } |
1025 | | |
1026 | | /*! |
1027 | | **\brief OBAngleData copy constructor |
1028 | | */ |
1029 | | OBAngleData::OBAngleData(const OBAngleData &src) |
1030 | 0 | : OBGenericData(src), _angles(src._angles) |
1031 | 0 | { } |
1032 | | |
1033 | | /*! |
1034 | | **\brief OBAngleData assignment operator |
1035 | | */ |
1036 | | OBAngleData& OBAngleData::operator =(const OBAngleData &src) |
1037 | 0 | { |
1038 | 0 | if (this == &src) |
1039 | 0 | return(*this); |
1040 | | |
1041 | 0 | _source = src._source; |
1042 | 0 | _angles = src._angles; |
1043 | |
|
1044 | 0 | return(*this); |
1045 | 0 | } |
1046 | | |
1047 | | /*! |
1048 | | **\brief sets OBAngleData to its original state |
1049 | | */ |
1050 | | void OBAngleData::Clear() |
1051 | 0 | { |
1052 | 0 | _angles.clear(); |
1053 | 0 | return; |
1054 | 0 | } |
1055 | | |
1056 | | /*! |
1057 | | **\brief Adds a new angle to OBAngleData |
1058 | | */ |
1059 | | void OBAngleData::SetData(OBAngle &angle) |
1060 | 0 | { |
1061 | 0 | _angles.push_back(angle); |
1062 | 0 | return; |
1063 | 0 | } |
1064 | | |
1065 | | /*! |
1066 | | **\brief Fills an array with the indices of the atoms in the angle (vertex first) |
1067 | | **\param angles pointer to the pointer to an array of angles atom indices |
1068 | | **\return True if successful |
1069 | | */ |
1070 | | bool OBAngleData::FillAngleArray(std::vector<std::vector<unsigned int> > &angles) |
1071 | 0 | { |
1072 | 0 | if(_angles.empty()) |
1073 | 0 | return(false); |
1074 | | |
1075 | 0 | vector<OBAngle>::iterator angle; |
1076 | |
|
1077 | 0 | angles.clear(); |
1078 | 0 | angles.resize(_angles.size()); |
1079 | |
|
1080 | 0 | unsigned int ct = 0; |
1081 | |
|
1082 | 0 | for( angle=_angles.begin(); angle!=_angles.end(); ++angle,ct++) |
1083 | 0 | { |
1084 | 0 | angles[ct].resize(3); |
1085 | 0 | angles[ct][0] = angle->_vertex->GetIdx() - 1; |
1086 | 0 | angles[ct][1] = angle->_termini.first->GetIdx() - 1; |
1087 | 0 | angles[ct][2] = angle->_termini.second->GetIdx() - 1; |
1088 | 0 | } |
1089 | |
|
1090 | 0 | return(true); |
1091 | 0 | } |
1092 | | |
1093 | | /*! |
1094 | | **\brief Fills an array with the indices of the atoms in the angle (vertex first) |
1095 | | **\param angles pointer to the pointer to an array of angles atom indices |
1096 | | **\param size the current number of rows in the array |
1097 | | **\return int The number of angles |
1098 | | */ |
1099 | | unsigned int OBAngleData::FillAngleArray(int **angles, unsigned int &size) |
1100 | 0 | { |
1101 | 0 | if(_angles.size() > size) |
1102 | 0 | { |
1103 | 0 | delete [] *angles; |
1104 | 0 | *angles = new int[_angles.size()*3]; |
1105 | 0 | size = (unsigned int)_angles.size(); |
1106 | 0 | } |
1107 | |
|
1108 | 0 | vector<OBAngle>::iterator angle; |
1109 | 0 | int angleIdx = 0; |
1110 | 0 | for( angle=_angles.begin(); angle!=_angles.end(); ++angle) |
1111 | 0 | { |
1112 | 0 | *angles[angleIdx++] = angle->_vertex->GetIdx(); |
1113 | 0 | *angles[angleIdx++] = angle->_termini.first->GetIdx(); |
1114 | 0 | *angles[angleIdx++] = angle->_termini.second->GetIdx(); |
1115 | 0 | } |
1116 | 0 | return (unsigned int)_angles.size(); |
1117 | 0 | } |
1118 | | |
1119 | | // |
1120 | | //member functions for OBAngleData class - stores OBAngle set |
1121 | | // |
1122 | | |
1123 | | /*! |
1124 | | **\brief OBTorsion constructor |
1125 | | */ |
1126 | | OBTorsion::OBTorsion(OBAtom *a,OBAtom *b, OBAtom *c,OBAtom *d) |
1127 | 0 | { |
1128 | 0 | triple<OBAtom*,OBAtom*,double> ad(a,d,0.0); |
1129 | 0 | _ads.push_back(ad); |
1130 | |
|
1131 | 0 | _bc.first = b; |
1132 | 0 | _bc.second = c; |
1133 | 0 | } |
1134 | | |
1135 | | /*! |
1136 | | **\brief OBTorsion copy constructor |
1137 | | */ |
1138 | | OBTorsion::OBTorsion(const OBTorsion &src) |
1139 | 0 | : _bc(src._bc), _ads(src._ads) |
1140 | 0 | {} |
1141 | | |
1142 | | /*! |
1143 | | **\brief Returns all the 4 atom sets in OBTorsion |
1144 | | */ |
1145 | | vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > OBTorsion::GetTorsions() |
1146 | 0 | { |
1147 | 0 | quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> abcd; |
1148 | |
|
1149 | 0 | abcd.second = _bc.first; |
1150 | 0 | abcd.third = _bc.second; |
1151 | |
|
1152 | 0 | vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > torsions; |
1153 | 0 | vector<triple<OBAtom*,OBAtom*,double> >::iterator ad; |
1154 | |
|
1155 | 0 | for(ad = _ads.begin();ad != _ads.end();++ad) |
1156 | 0 | { |
1157 | 0 | abcd.first = ad->first; |
1158 | 0 | abcd.fourth = ad->second; |
1159 | 0 | torsions.push_back(abcd); |
1160 | 0 | } |
1161 | |
|
1162 | 0 | return(torsions); |
1163 | 0 | } |
1164 | | |
1165 | | /*! |
1166 | | **\brief OBTorsion assignment operator |
1167 | | */ |
1168 | | OBTorsion& OBTorsion::operator =(const OBTorsion &src) |
1169 | 0 | { |
1170 | 0 | if (this == &src) |
1171 | 0 | return(*this); |
1172 | | |
1173 | 0 | _bc = src._bc; |
1174 | 0 | _ads = src._ads; |
1175 | |
|
1176 | 0 | return(*this); |
1177 | 0 | } |
1178 | | |
1179 | | /*! |
1180 | | **\brief Returns the OBTorsion to its original state |
1181 | | */ |
1182 | | void OBTorsion::Clear() |
1183 | 0 | { |
1184 | 0 | _bc.first = 0; |
1185 | 0 | _bc.second = 0; |
1186 | 0 | _ads.erase(_ads.begin(),_ads.end()); |
1187 | 0 | } |
1188 | | |
1189 | | /*! |
1190 | | **\brief Sets the angle of a torsion in OBTorsion |
1191 | | **\param radians the value to assign to the torsion |
1192 | | **\param index the index into the torsion of the OBTorsion |
1193 | | **\return boolean success |
1194 | | */ |
1195 | | bool OBTorsion::SetAngle(double radians,unsigned int index) |
1196 | 0 | { |
1197 | 0 | if(index >= _ads.size()) |
1198 | 0 | return(false); |
1199 | | |
1200 | 0 | _ads[index].third = radians; |
1201 | |
|
1202 | 0 | return(true); |
1203 | 0 | } |
1204 | | |
1205 | | /*! |
1206 | | **\brief Obtains the angle of a torsion in OBTorsion |
1207 | | **\param radians the value of the angle is set here |
1208 | | **\param index the index into the torsion of the OBTorsion |
1209 | | **\return boolean success |
1210 | | */ |
1211 | | bool OBTorsion::GetAngle(double &radians, unsigned int index) |
1212 | 0 | { |
1213 | 0 | if(index >= _ads.size()) |
1214 | 0 | return false; |
1215 | 0 | radians = _ads[index].third; |
1216 | 0 | return true; |
1217 | 0 | } |
1218 | | |
1219 | | unsigned int OBTorsion::GetBondIdx() |
1220 | 0 | { |
1221 | 0 | return(_bc.first->GetBond(_bc.second)->GetIdx()); |
1222 | 0 | } |
1223 | | |
1224 | | /*! |
1225 | | **\brief determines if torsion has only protons on either the a or d end |
1226 | | **\return boolean |
1227 | | */ |
1228 | | bool OBTorsion::IsProtonRotor() |
1229 | 0 | { |
1230 | 0 | bool Aprotor = true; |
1231 | 0 | bool Dprotor = true; |
1232 | 0 | vector<triple<OBAtom*,OBAtom*,double> >::iterator ad; |
1233 | 0 | for(ad = _ads.begin();ad != _ads.end() && (Aprotor || Dprotor);++ad) |
1234 | 0 | { |
1235 | 0 | if (ad->first->GetAtomicNum() != OBElements::Hydrogen) |
1236 | 0 | Aprotor = false; |
1237 | 0 | if (ad->second->GetAtomicNum() != OBElements::Hydrogen) |
1238 | 0 | Dprotor = false; |
1239 | 0 | } |
1240 | 0 | return (Aprotor || Dprotor); |
1241 | 0 | } |
1242 | | |
1243 | | /*! |
1244 | | **\brief adds a new torsion to the OBTorsion object |
1245 | | */ |
1246 | | bool OBTorsion::AddTorsion(OBAtom *a,OBAtom *b, OBAtom *c,OBAtom *d) |
1247 | 0 | { |
1248 | 0 | if(!Empty() && (b != _bc.first || c != _bc.second)) |
1249 | 0 | return(false); |
1250 | | |
1251 | 0 | if(Empty()) |
1252 | 0 | { |
1253 | 0 | _bc.first = b; |
1254 | 0 | _bc.second = c; |
1255 | 0 | } |
1256 | |
|
1257 | 0 | triple<OBAtom*,OBAtom*,double> ad(a,d,0.0); |
1258 | 0 | _ads.push_back(ad); |
1259 | |
|
1260 | 0 | return(true); |
1261 | 0 | } |
1262 | | |
1263 | | /*! |
1264 | | **\brief adds a new torsion to the OBTorsion object |
1265 | | */ |
1266 | | bool OBTorsion::AddTorsion(quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> &atoms) |
1267 | 0 | { |
1268 | 0 | if(!Empty() && (atoms.second != _bc.first || atoms.third != _bc.second)) |
1269 | 0 | return(false); |
1270 | | |
1271 | 0 | if(Empty()) |
1272 | 0 | { |
1273 | 0 | _bc.first = atoms.second; |
1274 | 0 | _bc.second = atoms.third; |
1275 | 0 | } |
1276 | |
|
1277 | 0 | triple<OBAtom*,OBAtom*,double> ad(atoms.first,atoms.fourth,0.0); |
1278 | 0 | _ads.push_back(ad); |
1279 | |
|
1280 | 0 | return(true); |
1281 | 0 | } |
1282 | | |
1283 | | //\!brief OBTorsionData ctor |
1284 | | OBTorsionData::OBTorsionData() |
1285 | 0 | : OBGenericData("TorsionData", OBGenericDataType::TorsionData) |
1286 | 0 | { } |
1287 | | |
1288 | | // |
1289 | | //member functions for OBTorsionData class - stores OBTorsion set |
1290 | | // |
1291 | | OBTorsionData::OBTorsionData(const OBTorsionData &src) |
1292 | 0 | : OBGenericData(src), _torsions(src._torsions) |
1293 | 0 | { } |
1294 | | |
1295 | | OBTorsionData& OBTorsionData::operator =(const OBTorsionData &src) |
1296 | 0 | { |
1297 | 0 | if (this == &src) |
1298 | 0 | return(*this); |
1299 | | |
1300 | 0 | OBGenericData::operator =(src); |
1301 | |
|
1302 | 0 | _source = src._source; |
1303 | 0 | _torsions = src._torsions; |
1304 | |
|
1305 | 0 | return(*this); |
1306 | 0 | } |
1307 | | |
1308 | | void OBTorsionData::Clear() |
1309 | 0 | { |
1310 | 0 | _torsions.clear(); |
1311 | 0 | } |
1312 | | |
1313 | | void OBTorsionData::SetData(OBTorsion &torsion) |
1314 | 0 | { |
1315 | 0 | _torsions.push_back(torsion); |
1316 | 0 | } |
1317 | | |
1318 | | /*! |
1319 | | **\brief Fills a vector with the indices of the atoms in torsions (ordered abcd) |
1320 | | **\param torsions reference to the vector of abcd atom sets |
1321 | | **\return boolean success |
1322 | | */ |
1323 | | bool OBTorsionData::FillTorsionArray(std::vector<std::vector<unsigned int> > &torsions) |
1324 | 0 | { |
1325 | 0 | if(_torsions.empty()) |
1326 | 0 | return(false); |
1327 | | |
1328 | 0 | vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > tmpquads,quads; |
1329 | 0 | vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> >::iterator thisQuad; |
1330 | 0 | vector<OBTorsion>::iterator torsion; |
1331 | | |
1332 | | //generate set of all 4 atom abcd's from torsion structure |
1333 | 0 | for (torsion = _torsions.begin();torsion != _torsions.end();++torsion) |
1334 | 0 | { |
1335 | 0 | tmpquads = torsion->GetTorsions(); |
1336 | 0 | for(thisQuad = tmpquads.begin();thisQuad != tmpquads.end();++thisQuad) |
1337 | 0 | quads.push_back(*thisQuad); |
1338 | 0 | } |
1339 | | |
1340 | | //fill array of torsion atoms |
1341 | |
|
1342 | 0 | torsions.clear(); |
1343 | 0 | torsions.resize(quads.size()); |
1344 | |
|
1345 | 0 | unsigned int ct = 0; |
1346 | |
|
1347 | 0 | for (thisQuad = quads.begin();thisQuad != quads.end();++thisQuad,++ct) |
1348 | 0 | { |
1349 | 0 | torsions[ct].resize(4); |
1350 | 0 | torsions[ct][0] = thisQuad->first->GetIdx()-1; |
1351 | 0 | torsions[ct][1] = thisQuad->second->GetIdx()-1; |
1352 | 0 | torsions[ct][2] = thisQuad->third->GetIdx()-1; |
1353 | 0 | torsions[ct][3] = thisQuad->fourth->GetIdx()-1; |
1354 | 0 | } |
1355 | |
|
1356 | 0 | return(true); |
1357 | 0 | } |
1358 | | |
1359 | | |
1360 | | // |
1361 | | //member functions for OBDOSData class |
1362 | | // |
1363 | | |
1364 | | /*! |
1365 | | **\brief Assign the data |
1366 | | **\param fermi The Fermi energy in eV |
1367 | | **\param vEnergies Energy levels in eV |
1368 | | **\param vDensities Density of states in (number of states) / (unit cell) |
1369 | | **\param vIntegration Integrated DOS |
1370 | | */ |
1371 | | void OBDOSData::SetData(double fermi, |
1372 | | const std::vector<double> & vEnergies, |
1373 | | const std::vector<double> & vDensities, |
1374 | | const std::vector<double> & vIntegration) |
1375 | 0 | { |
1376 | 0 | this->_fermi = fermi; |
1377 | 0 | this->_vEnergies = vEnergies; |
1378 | 0 | this->_vIntegration = vIntegration; |
1379 | 0 | this->_vDensities = vDensities; |
1380 | 0 | } |
1381 | | |
1382 | | // member functions for OBOrbitalData |
1383 | | |
1384 | | void OBOrbitalData::LoadClosedShellOrbitals(std::vector<double> energies, std::vector<std::string> symmetries, unsigned int alphaHOMO) |
1385 | 0 | { |
1386 | 0 | if (energies.size() < symmetries.size()) |
1387 | 0 | return; // something is very weird -- it's OK to pass no symmetries (we'll assume "A") |
1388 | 0 | if (energies.size() == 0) |
1389 | 0 | return; |
1390 | 0 | if (alphaHOMO > energies.size()) |
1391 | 0 | return; |
1392 | | |
1393 | 0 | _alphaHOMO = alphaHOMO; |
1394 | 0 | _alphaOrbitals.clear(); |
1395 | 0 | _betaHOMO = 0; |
1396 | 0 | _betaOrbitals.clear(); |
1397 | 0 | _openShell = false; |
1398 | |
|
1399 | 0 | if (symmetries.size() < energies.size()) // pad with "A" symmetry |
1400 | 0 | for (unsigned int i = symmetries.size(); i < energies.size(); ++i) |
1401 | 0 | symmetries.push_back("A"); |
1402 | |
|
1403 | 0 | OBOrbital currentOrbital; |
1404 | 0 | for (unsigned int i = 0; i < energies.size(); ++i) |
1405 | 0 | { |
1406 | 0 | if (i < alphaHOMO) |
1407 | 0 | currentOrbital.SetData(energies[i], 2.0, symmetries[i]); |
1408 | 0 | else |
1409 | 0 | currentOrbital.SetData(energies[i], 0.0, symmetries[i]); |
1410 | |
|
1411 | 0 | _alphaOrbitals.push_back(currentOrbital); |
1412 | 0 | } |
1413 | 0 | } |
1414 | | |
1415 | | void OBOrbitalData::LoadAlphaOrbitals(std::vector<double> energies, std::vector<std::string> symmetries, unsigned int alphaHOMO) |
1416 | 0 | { |
1417 | 0 | if (energies.size() < symmetries.size()) |
1418 | 0 | return; // something is very weird -- it's OK to pass no symmetries (we'll assume "A") |
1419 | 0 | if (energies.size() == 0) |
1420 | 0 | return; |
1421 | 0 | if (alphaHOMO > energies.size()) |
1422 | 0 | return; |
1423 | | |
1424 | 0 | _alphaHOMO = alphaHOMO; |
1425 | 0 | _alphaOrbitals.clear(); |
1426 | 0 | _openShell = true; |
1427 | |
|
1428 | 0 | if (symmetries.size() < energies.size()) // pad with "A" symmetry |
1429 | 0 | for (unsigned int i = symmetries.size(); i < energies.size(); ++i) |
1430 | 0 | symmetries.push_back("A"); |
1431 | |
|
1432 | 0 | OBOrbital currentOrbital; |
1433 | 0 | for (unsigned int i = 0; i < energies.size(); ++i) |
1434 | 0 | { |
1435 | 0 | if (i < alphaHOMO) |
1436 | 0 | currentOrbital.SetData(energies[i], 2.0, symmetries[i]); |
1437 | 0 | else |
1438 | 0 | currentOrbital.SetData(energies[i], 0.0, symmetries[i]); |
1439 | |
|
1440 | 0 | _alphaOrbitals.push_back(currentOrbital); |
1441 | 0 | } |
1442 | 0 | } |
1443 | | |
1444 | | void OBOrbitalData::LoadBetaOrbitals(std::vector<double> energies, std::vector<std::string> symmetries, unsigned int betaHOMO) |
1445 | 0 | { |
1446 | 0 | if (energies.size() < symmetries.size()) |
1447 | 0 | return; // something is very weird -- it's OK to pass no symmetries (we'll assume "A") |
1448 | 0 | if (energies.size() == 0) |
1449 | 0 | return; |
1450 | 0 | if (betaHOMO > energies.size()) |
1451 | 0 | return; |
1452 | | |
1453 | 0 | _betaHOMO = betaHOMO; |
1454 | 0 | _betaOrbitals.clear(); |
1455 | 0 | _openShell = true; |
1456 | |
|
1457 | 0 | if (symmetries.size() < energies.size()) // pad with "A" symmetry |
1458 | 0 | for (unsigned int i = symmetries.size(); i < energies.size(); ++i) |
1459 | 0 | symmetries.push_back("A"); |
1460 | |
|
1461 | 0 | OBOrbital currentOrbital; |
1462 | 0 | for (unsigned int i = 0; i < energies.size(); ++i) |
1463 | 0 | { |
1464 | 0 | if (i < betaHOMO) |
1465 | 0 | currentOrbital.SetData(energies[i], 2.0, symmetries[i]); |
1466 | 0 | else |
1467 | 0 | currentOrbital.SetData(energies[i], 0.0, symmetries[i]); |
1468 | |
|
1469 | 0 | _betaOrbitals.push_back(currentOrbital); |
1470 | 0 | } |
1471 | 0 | } |
1472 | | |
1473 | | // |
1474 | | //member functions for OBElectronicTransitionData class |
1475 | | // |
1476 | | |
1477 | | /*! |
1478 | | **\brief Assign the basic excitation data |
1479 | | **\param vWavelengths Wavelengths in nm |
1480 | | **\param vForces Oscillator strengths |
1481 | | */ |
1482 | | void OBElectronicTransitionData::SetData(const std::vector<double> & vWavelengths, |
1483 | | const std::vector<double> & vForces) |
1484 | 0 | { |
1485 | 0 | this->_vWavelengths = vWavelengths; |
1486 | 0 | this->_vForces = vForces; |
1487 | 0 | } |
1488 | | |
1489 | | /*! |
1490 | | **\brief Assign the electronic dipole strengths |
1491 | | **\param vEDipole Electronic dipole moment strength |
1492 | | */ |
1493 | | void OBElectronicTransitionData::SetEDipole(const std::vector<double> & vEDipole) |
1494 | 0 | { |
1495 | 0 | this->_vEDipole = vEDipole; |
1496 | 0 | } |
1497 | | |
1498 | | /*! |
1499 | | **\brief Assign the rotatory strengths (velocity) |
1500 | | **\param vRotatoryStrengthsVelocity Vector containing the rotatory strengths |
1501 | | */ |
1502 | | void OBElectronicTransitionData::SetRotatoryStrengthsVelocity(const std::vector<double> & vRotatoryStrengthsVelocity) |
1503 | 0 | { |
1504 | 0 | this->_vRotatoryStrengthsVelocity = vRotatoryStrengthsVelocity; |
1505 | 0 | } |
1506 | | |
1507 | | /*! |
1508 | | **\brief Assign the rotatory strengths (length) |
1509 | | **\param vRotatoryStrengthsLength Vector containing the rotatory strengths |
1510 | | */ |
1511 | | void OBElectronicTransitionData::SetRotatoryStrengthsLength(const std::vector<double> & vRotatoryStrengthsLength) |
1512 | 0 | { |
1513 | 0 | this->_vRotatoryStrengthsLength = vRotatoryStrengthsLength; |
1514 | 0 | } |
1515 | | |
1516 | | // |
1517 | | //member functions for OBVibrationData class |
1518 | | // |
1519 | | |
1520 | | /*! |
1521 | | **\brief Assign the data |
1522 | | **\param vLx Normal modes in 1/sqrt(a.u.) |
1523 | | **\param vFrequencies Harmonic frequencies in inverse centimeters |
1524 | | **\param vIntensities Infrared absorption intensities in KM/Mole |
1525 | | */ |
1526 | | void OBVibrationData::SetData(const std::vector< std::vector< vector3 > > & vLx, |
1527 | | const std::vector<double> & vFrequencies, |
1528 | | const std::vector<double> & vIntensities) |
1529 | 0 | { |
1530 | 0 | this->_vLx = vLx; |
1531 | 0 | this->_vFrequencies = vFrequencies; |
1532 | 0 | this->_vIntensities = vIntensities; |
1533 | 0 | } |
1534 | | |
1535 | | /*! |
1536 | | **\brief Assign the data |
1537 | | **\param vLx Normal modes in 1/sqrt(a.u.) |
1538 | | **\param vFrequencies Harmonic frequencies in inverse centimeters |
1539 | | **\param vIntensities Infrared absorption intensities in KM/Mole |
1540 | | **\param vRamanActivities Raman activities |
1541 | | */ |
1542 | | void OBVibrationData::SetData(const std::vector< std::vector< vector3 > > & vLx, |
1543 | | const std::vector<double> & vFrequencies, |
1544 | | const std::vector<double> & vIntensities, |
1545 | | const std::vector<double> & vRamanActivities) |
1546 | 0 | { |
1547 | 0 | this->_vLx = vLx; |
1548 | 0 | this->_vFrequencies = vFrequencies; |
1549 | 0 | this->_vIntensities = vIntensities; |
1550 | 0 | this->_vRamanActivities = vRamanActivities; |
1551 | 0 | } |
1552 | | |
1553 | | |
1554 | | /*! |
1555 | | **\brief Get the number of frequencies |
1556 | | */ |
1557 | | unsigned int OBVibrationData::GetNumberOfFrequencies() const |
1558 | 0 | { |
1559 | 0 | return this->_vFrequencies.size(); |
1560 | 0 | } |
1561 | | |
1562 | | void OBFreeGrid::Clear() |
1563 | 0 | { |
1564 | 0 | _points.clear(); |
1565 | 0 | } |
1566 | | |
1567 | | } //end namespace OpenBabel |
1568 | | |
1569 | | //! \file generic.cpp |
1570 | | //! \brief Handle OBGenericData classes. Custom data for atoms, bonds, etc. |