ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/openbabel/generic.cpp
Revision: 2518
Committed: Fri Dec 16 21:52:50 2005 UTC (18 years, 6 months ago) by tim
File size: 25174 byte(s)
Log Message:
changed __FUNCTION__ to __func__ to match C99 standard, and then added
an autoconf test to check for __func__ usability.  Changed some default
compile flags for the Sun architecture

File Contents

# Content
1 /**********************************************************************
2 generic.cpp - Handle OBGenericData classes.
3
4 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6
7 This file is part of the Open Babel project.
8 For more information, see <http://openbabel.sourceforge.net/>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation version 2 of the License.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 ***********************************************************************/
19
20 #include "mol.hpp"
21 #include "matrix3x3.hpp"
22
23 using namespace std;
24
25 namespace OpenBabel
26 {
27
28 /** \class OBGenericData
29
30 OBGenericData is an abstract base class which defines an interface for
31 storage, retrieval, and indexing of arbitrary generic data.
32 Subclasses of OBGenericData can be used to store custom data
33 on a per-atom, per-bond, per-molecule, or per-residue basis.
34 Open Babel currently supports a small subset of chemical functionality
35 as OBGenericData types, which will expand over time to support additional
36 interconversion (e.g., spectroscopy, dynamics, surfaces...)
37
38 For your own custom data, either define a custom subclass using
39 an id from the OBGenericDataType::CustomData0 to OBGenericDataType::CustomData15 slots,
40 or store your data as a string and use OBPairData for key/value access.
41 The latter is <strong>highly</strong> recommended for various text descriptors
42 e.g., in QSAR, atom or bond labels, or other textual data.
43
44 Example code using OBGenericData
45
46 @code
47 if (mol.HasData(OBGenericDataType::UnitCell))
48 {
49 uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell);
50 sprintf(buffer,
51 "%10.5f%10.5f%10.5f%10.5f%10.5f%10.5f",
52 uc->GetA(), uc->GetB(), uc->GetC(),
53 uc->GetAlpha() , uc->GetBeta(), uc->GetGamma());
54 ofs << buffer << endl;
55 }
56
57 ...
58
59 vector<OBGenericData*>::iterator k;
60 vector<OBGenericData*> vdata = mol.GetData();
61 for (k = vdata.begin();k != vdata.end();k++)
62 if ((*k)->GetDataType() == OBGenericDataType::PairData)
63 {
64 ofs << "> <" << (*k)->GetAttribute() << ">" << endl;
65 ofs << ((OBPairData*)(*k))->GetValue() << endl << endl;
66 }
67 @endcode
68
69 Similar code also works for OBGenericData stored in an OBAtom or OBBond (or OBResidue).
70
71 @code
72 if (!atom.HasData("UserLabel")) // stored textual data as an OBPairData
73 {
74 OBPairData *label = new OBPairData;
75 label->SetAttribute("UserLabel");
76 label->SetValue(userInput);
77
78 atom.SetData(label);
79 }
80
81 ...
82
83 if (bond.HasData("DisplayType")) // e.g. in a visualization tool
84 {
85 OBPairData *display = dynamic_cast<OBPairData *> bond.GetData("DisplayType");
86 if (display->GetValue() == "wireframe")
87 {
88 ... // display a wireframe view
89 }
90 }
91 @endcode
92
93 **/
94
95 //
96 //member functions for OBGenericData class
97 //
98
99 OBGenericData::OBGenericData()
100 {
101 _type = OBGenericDataType::UndefinedData;
102 _attr = "undefined";
103 }
104
105 OBGenericData::OBGenericData(const OBGenericData &src)
106 {
107 _type = src.GetDataType();
108 _attr = src.GetAttribute();
109 }
110
111
112 OBGenericData& OBGenericData::operator = (const OBGenericData &src)
113 {
114 if(this == &src)
115 return(*this);
116
117 _type = src._type;
118 _attr = src._attr;
119
120 return(*this);
121 }
122
123 //
124 //member functions for OBCommentData class
125 //
126
127 OBCommentData::OBCommentData()
128 {
129 _type = OBGenericDataType::CommentData;
130 _attr = "Comment";
131 }
132
133 OBCommentData::OBCommentData(const OBCommentData &src) :
134 OBGenericData()
135 {
136 _type = OBGenericDataType::CommentData;
137 _attr = "Comment";
138 _data = src.GetData();
139 }
140
141 //
142 //member functions for OBExternalBond class
143 //
144 OBExternalBond::OBExternalBond(OBAtom *atom,OBBond *bond,int idx)
145 {
146 _idx = idx;
147 _atom = atom;
148 _bond = bond;
149 }
150
151 OBExternalBond::OBExternalBond(const OBExternalBond &src)
152 {
153 _idx = src.GetIdx();
154 _atom = src.GetAtom();
155 _bond = src.GetBond();
156 }
157
158 //
159 //member functions for OBExternalBondData class
160 //
161
162 OBExternalBondData::OBExternalBondData()
163 {
164 _type = OBGenericDataType::ExternalBondData;
165 _attr = "ExternalBondData";
166 }
167
168 void OBExternalBondData::SetData(OBAtom *atom,OBBond *bond,int idx)
169 {
170 OBExternalBond xb(atom,bond,idx);
171 _vexbnd.push_back(xb);
172 }
173
174 //
175 //member functions for OBPairData class
176 //
177
178 OBPairData::OBPairData()
179 {
180 _type = OBGenericDataType::PairData;
181 _attr = "PairData";
182 }
183
184 //
185 //member functions for OBVirtualBond class
186 //
187
188 OBVirtualBond::OBVirtualBond()
189 {
190 _type = OBGenericDataType::VirtualBondData;
191 _attr = "VirtualBondData";
192 _bgn = _end = _ord = 0;
193 }
194
195 OBVirtualBond::OBVirtualBond(int bgn,int end,int ord,int stereo)
196 {
197 _type = OBGenericDataType::VirtualBondData;
198 _attr = "VirtualBondData";
199 _bgn = bgn;
200 _end = end;
201 _ord = ord;
202 _stereo = stereo;
203 }
204
205 //
206 // member functions for OBUnitCell class
207 //
208 OBUnitCell::OBUnitCell()
209 {
210 _a = _b = _c = _alpha = _beta = _gamma = 0.0;
211 _type = OBGenericDataType::UnitCell;
212 _attr = "UnitCell";
213 }
214
215 OBUnitCell::OBUnitCell(const OBUnitCell &src) :
216 OBGenericData()
217 {
218 _a = src._a;
219 _b = src._b;
220 _c = src._c;
221 _alpha = src._alpha;
222 _beta = src._beta;
223 _gamma = src._gamma;
224 _offset = src._offset;
225
226 _v1 = src._v1;
227 _v2 = src._v2;
228 _v3 = src._v3;
229
230 _spaceGroup = src._spaceGroup;
231 }
232
233 OBUnitCell & OBUnitCell::operator=(const OBUnitCell &src)
234 {
235 if(this == &src)
236 return(*this);
237
238 _a = src._a;
239 _b = src._b;
240 _c = src._c;
241 _alpha = src._alpha;
242 _beta = src._beta;
243 _gamma = src._gamma;
244 _offset = src._offset;
245
246 _v1 = src._v1;
247 _v2 = src._v2;
248 _v3 = src._v3;
249
250 _spaceGroup = src._spaceGroup;
251
252 return(*this);
253 }
254
255 //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#convertCartesianIntoNotionalCoordinates">blue-obelisk:convertCartesianIntoNotionalCoordinates</a>
256 void OBUnitCell::SetData(const vector3 v1, const vector3 v2, const vector3 v3)
257 {
258 _a = v1.length();
259 _b = v2.length();
260 _c = v3.length();
261 _alpha = vectorAngle(v2, v3);
262 _beta = vectorAngle(v1, v3);
263 _gamma = vectorAngle(v1, v2);
264 _v1 = v1;
265 _v2 = v2;
266 _v3 = v3;
267 }
268
269 //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#convertNotionalIntoCartesianCoordinates">blue-obelisk:convertNotionalIntoCartesianCoordinates</a>
270 vector<vector3> OBUnitCell::GetCellVectors()
271 {
272 vector<vector3> v;
273 v.reserve(3);
274
275 if (_v1.length() == 0 && _v2.length() == 0 && _v3.length() == 0)
276 {
277 vector3 temp;
278 matrix3x3 m = GetOrthoMatrix();
279
280 temp = vector3(1.0f, 0.0f, 0.0f);
281 v.push_back(m * temp);
282 temp = vector3(0.0f, 1.0f, 0.0f);
283 v.push_back(m * temp);
284 temp = vector3(0.0f, 0.0f, 1.0f);
285 v.push_back(m * temp);
286 }
287 else
288 {
289 v.push_back(_v1);
290 v.push_back(_v2);
291 v.push_back(_v3);
292 }
293
294 return v;
295 }
296
297 matrix3x3 OBUnitCell::GetCellMatrix()
298 {
299 matrix3x3 m;
300
301 if (_v1.length() == 0 && _v2.length() == 0 && _v3.length() == 0)
302 {
303 m = GetOrthoMatrix();
304 }
305 else
306 {
307 vector3 v1, v2, v3;
308 v1 = _v1;
309 v2 = _v2;
310 v3 = _v3;
311 m = matrix3x3(v1,v2,v3);
312 }
313 return m;
314 }
315
316 //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#calculateOrthogonalisationMatrix">blue-obelisk:calculateOrthogonalisationMatrix</a>
317 matrix3x3 OBUnitCell::GetOrthoMatrix()
318 {
319 matrix3x3 m;
320
321 // already here, let's not duplicate the work
322 m.FillOrth(_alpha, _beta, _gamma, _a, _b, _c);
323
324 return m;
325 }
326
327 // Based on code in PyMMLib: http://pymmlib.sf.net/
328 //! Matrix to convert from Cartesian to fractional
329 //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#convertCartesianIntoFractionalCoordinates">blue-obelisk:convertCartesianIntoFractionalCoordinates</a>
330 matrix3x3 OBUnitCell::GetFractionalMatrix()
331 {
332 matrix3x3 m;
333 double sinAlpha, sinBeta, sinGamma;
334 double cosAlpha, cosBeta, cosGamma;
335 double v;
336
337 sinAlpha = sin(_alpha * DEG_TO_RAD);
338 sinBeta = sin(_beta * DEG_TO_RAD);
339 sinGamma = sin(_gamma * DEG_TO_RAD);
340 cosAlpha = cos(_alpha * DEG_TO_RAD);
341 cosBeta = cos(_beta * DEG_TO_RAD);
342 cosGamma = cos(_gamma * DEG_TO_RAD);
343
344 v = sqrt(1 - SQUARE(cosAlpha) - SQUARE(cosBeta) - SQUARE(cosGamma) +
345 2 * cosAlpha*cosBeta*cosGamma);
346
347 m.Set(0,0, 1.0f / _a);
348 m.Set(0,1, -cosGamma / (_a * sinGamma) );
349 m.Set(0,2, (cosGamma * cosAlpha - cosBeta) / (_a * v * sinGamma) );
350 m.Set(1,0, 0.0);
351 m.Set(1,1, 1.0f / (_b * sinGamma) );
352 m.Set(1,2, (cosGamma * cosBeta - cosAlpha) / (_b * v * sinGamma) );
353 m.Set(2,0, 0.0);
354 m.Set(2,1, 0.0);
355 m.Set(2,2, sinGamma / (_c * v) );
356
357 return m;
358 }
359
360 //
361 // member functions for OBSymmetryData class
362 //
363 OBSymmetryData::OBSymmetryData()
364 {
365 _type = OBGenericDataType::SymmetryData;
366 _attr = "Symmetry";
367 }
368
369 OBSymmetryData::OBSymmetryData(const OBSymmetryData &src) :
370 OBGenericData()
371 {
372 _pointGroup = src._pointGroup;
373 _spaceGroup = src._spaceGroup;
374 }
375
376 OBSymmetryData & OBSymmetryData::operator=(const OBSymmetryData &src)
377 {
378 if(this == &src)
379 return(*this);
380
381 _pointGroup = src._pointGroup;
382 _spaceGroup = src._spaceGroup;
383
384 return(*this);
385 }
386
387 OBConformerData::OBConformerData()
388 {
389 _type = OBGenericDataType::ConformerData;
390 _attr = "Conformers";
391 }
392
393 OBConformerData::OBConformerData(const OBConformerData &src) :
394 OBGenericData()
395 {
396 _vDimension = src._vDimension;
397 _vEnergies = src._vEnergies;
398 _vForces = src._vForces;
399 _vVelocity = src._vVelocity;
400 _vDisplace = src._vDisplace;
401 _vData = src._vData;
402 }
403
404 OBConformerData & OBConformerData::operator=(const OBConformerData &src)
405 {
406 if(this == &src)
407 return(*this);
408
409 _vDimension = src._vDimension;
410 _vEnergies = src._vEnergies;
411 _vForces = src._vForces;
412 _vVelocity = src._vVelocity;
413 _vDisplace = src._vDisplace;
414 _vData = src._vData;
415
416 return(*this);
417 }
418
419 //
420 //member functions for OBRingData class
421 //
422
423 OBRingData::OBRingData()
424 {
425 _type = OBGenericDataType::RingData;
426 _attr = "RingData";
427 _vr.clear();
428 }
429
430 /*!
431 **\brief OBRingData copy constructor
432 **\param src reference to original OBRingData object (rhs)
433 */
434 OBRingData::OBRingData(const OBRingData &src)
435 : OBGenericData(src), //chain to base class
436 _vr(src._vr) //chain to member classes
437 {
438 //no other memeber data
439 //memory management
440
441 vector<OBRing*>::iterator ring;
442
443 for(ring = _vr.begin();ring != _vr.end();ring++)
444 {
445 OBRing *newring = new OBRing;
446 (*newring) = (**ring); //copy data to new object
447 (*ring) = newring; //repoint new pointer to new copy of data
448 }
449 }
450
451 OBRingData::~OBRingData()
452 {
453 vector<OBRing*>::iterator ring;
454 for (ring = _vr.begin();ring != _vr.end();ring++)
455 {
456 delete *ring;
457 }
458 }
459
460 /*!
461 **\brief OBRingData assignment operator
462 **\param src reference to original OBRingData object (rhs)
463 **\return reference to changed OBRingData object (lhs)
464 */
465 OBRingData& OBRingData::operator =(const OBRingData &src)
466 {
467 //on identity, return
468 if(this == &src)
469 return(*this);
470
471 //chain to base class
472 OBGenericData::operator =(src);
473
474 //member data
475
476 //memory management
477 vector<OBRing*>::iterator ring;
478 for(ring = _vr.begin();ring != _vr.end();ring++)
479 {
480 delete &*ring; //deallocate old rings to prevent memory leak
481 }
482
483 _vr.clear();
484 _vr = src._vr; //copy vector properties
485
486 for(ring = _vr.begin();ring != _vr.end();ring++)
487 {
488 if(*ring == 0)
489 continue;
490
491 //allocate and copy ring data
492 OBRing *newring = new OBRing;
493 (*newring) = (**ring);
494 (*ring) = newring; //redirect pointer
495 }
496 return(*this);
497 }
498
499 //
500 //member functions for OBAngle class - stores all angles
501 //
502
503 /*!
504 **\brief Angle default constructor
505 */
506 OBAngle::OBAngle()
507 {
508 _vertex = 0;
509 _termini.first = 0;
510 _termini.second = 0;
511 _radians = 0.0;
512 }
513
514 /*!
515 **\brief Angle constructor
516 */
517 OBAngle::OBAngle(OBAtom *vertex,OBAtom *a,OBAtom *b)
518 {
519 _vertex = vertex;
520 _termini.first = a;
521 _termini.second = b ;
522
523 SortByIndex();
524 }
525
526 /*!
527 **\brief OBAngle copy constructor
528 */
529 OBAngle::OBAngle(const OBAngle &src)
530 : _termini(src._termini)
531 {
532 _vertex = src._vertex;
533 _radians = src._radians;
534 }
535
536 /*!
537 **\brief OBAngle assignment operator
538 */
539 OBAngle& OBAngle::operator = (const OBAngle &src)
540 {
541 if (this == &src)
542 return(*this);
543
544 _vertex = src._vertex;
545 _termini.first = src._termini.first;
546 _termini.second = src._termini.second;
547 _radians = src._radians;
548
549 return(*this);
550 }
551
552 /*!
553 **\brief Return OBAngle to its original state
554 */
555 void OBAngle::Clear()
556 {
557 _vertex = 0;
558 _termini.first = 0;
559 _termini.second = 0;
560 _radians = 0.0;
561 return;
562 }
563
564 /*!
565 **\brief Sets the 3 atoms in the angle
566 ** Parameters are pointers to each OBAtom
567 */
568 void OBAngle::SetAtoms(OBAtom *vertex,OBAtom *a,OBAtom *b)
569 {
570 _vertex = vertex;
571 _termini.first = a;
572 _termini.second = b;
573 SortByIndex();
574 return;
575 }
576
577 /*!
578 **\brief Sets the 3 atoms in the angle
579 **\param atoms a triple of OBAtom pointers, the first must be the vertex
580 */
581 void OBAngle::SetAtoms(triple<OBAtom*,OBAtom*,OBAtom*> &atoms)
582 {
583 _vertex = atoms.first;
584 _termini.first = atoms.second;
585 _termini.second = atoms.third;
586 SortByIndex();
587 return;
588 }
589
590 /*!
591 **\brief Retrieves the 3 atom pointer for the angle (vertex first)
592 **\return triple of OBAtom pointers
593 */
594 triple<OBAtom*,OBAtom*,OBAtom*> OBAngle::GetAtoms()
595 {
596 triple<OBAtom*,OBAtom*,OBAtom*> atoms;
597 atoms.first = _vertex;
598 atoms.second = _termini.first;
599 atoms.third = _termini.second;
600 return(atoms);
601 }
602
603 /*!
604 **\brief sorts atoms in angle by order of indices
605 */
606 void OBAngle::SortByIndex()
607 {
608 OBAtom *tmp;
609
610 if(_termini.first->GetIdx() > _termini.second->GetIdx())
611 {
612 tmp = _termini.first;
613 _termini.first = _termini.second;
614 _termini.second = tmp;
615 }
616 }
617
618 /*!
619 **\brief OBAngle equality operator, is same angle, NOT same value
620 **\return boolean equality
621 */
622 bool OBAngle::operator ==(const OBAngle &other)
623 {
624 return ((_vertex == other._vertex) &&
625 (_termini.first == other._termini.first) &&
626 (_termini.second == other._termini.second));
627 }
628
629 //
630 //member functions for OBAngleData class - stores OBAngle set
631 //
632
633 /*!
634 **\brief OBAngleData constructor
635 */
636 OBAngleData::OBAngleData()
637 : OBGenericData()
638 {
639 _type = OBGenericDataType::AngleData;
640 _attr = "AngleData";
641 }
642
643 /*!
644 **\brief OBAngleData copy constructor
645 */
646 OBAngleData::OBAngleData(const OBAngleData &src)
647 : OBGenericData(src), _angles(src._angles)
648 {
649 _type = OBGenericDataType::AngleData;
650 _attr = "AngleData";
651 }
652
653 /*!
654 **\brief OBAngleData assignment operator
655 */
656 OBAngleData& OBAngleData::operator =(const OBAngleData &src)
657 {
658 if (this == &src)
659 return(*this);
660
661 _angles = src._angles;
662
663 return(*this);
664 }
665
666 /*!
667 **\brief sets OBAngleData to its original state
668 */
669 void OBAngleData::Clear()
670 {
671 _angles.clear();
672 return;
673 }
674
675 /*!
676 **\brief Adds a new angle to OBAngleData
677 */
678 void OBAngleData::SetData(OBAngle &angle)
679 {
680 _angles.push_back(angle);
681 return;
682 }
683
684 /*!
685 **\brief Fills an array with the indices of the atoms in the angle (vertex first)
686 **\param angles pointer to the pointer to an array of angles atom indices
687 **\param size the current number of rows in the array
688 **\return int The number of angles
689 */
690 unsigned int OBAngleData::FillAngleArray(int **angles, unsigned int &size)
691 {
692 if(_angles.size() > size)
693 {
694 delete [] *angles;
695 *angles = new int[_angles.size()*3];
696 size = (unsigned int)_angles.size();
697 }
698
699 vector<OBAngle>::iterator angle;
700 int angleIdx = 0;
701 for( angle=_angles.begin(); angle!=_angles.end(); angle++)
702 {
703 *angles[angleIdx++] = angle->_vertex->GetIdx();
704 *angles[angleIdx++] = angle->_termini.first->GetIdx();
705 *angles[angleIdx++] = angle->_termini.second->GetIdx();
706 }
707 return (unsigned int)_angles.size();
708 }
709
710 //
711 //member functions for OBAngleData class - stores OBAngle set
712 //
713
714 /*!
715 **\brief OBTorsion constructor
716 */
717 OBTorsion::OBTorsion(OBAtom *a,OBAtom *b, OBAtom *c,OBAtom *d)
718 {
719 triple<OBAtom*,OBAtom*,double> ad(a,d,0.0);
720 _ads.push_back(ad);
721
722 _bc.first = b;
723 _bc.second = c;
724 }
725
726 /*!
727 **\brief OBTorsion copy constructor
728 */
729 OBTorsion::OBTorsion(const OBTorsion &src)
730 : _bc(src._bc), _ads(src._ads)
731 {}
732
733 /*!
734 **\brief Returns all the 4 atom sets in OBTorsion
735 */
736 vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > OBTorsion::GetTorsions()
737 {
738 quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> abcd;
739
740 abcd.second = _bc.first;
741 abcd.third = _bc.second;
742
743 vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > torsions;
744 vector<triple<OBAtom*,OBAtom*,double> >::iterator ad;
745
746 for(ad = _ads.begin();ad != _ads.end();ad++)
747 {
748 abcd.first = ad->first;
749 abcd.fourth = ad->second;
750 torsions.push_back(abcd);
751 }
752
753 return(torsions);
754 }
755
756 /*!
757 **\brief OBTorsion assignment operator
758 */
759 OBTorsion& OBTorsion::operator =(const OBTorsion &src)
760 {
761 if (this == &src)
762 return(*this);
763
764 _bc = src._bc;
765 _ads = src._ads;
766
767 return(*this);
768 }
769
770 /*!
771 **\brief Returns the OBTorsion to its original state
772 */
773 void OBTorsion::Clear()
774 {
775 _bc.first = 0;
776 _bc.second = 0;
777 _ads.erase(_ads.begin(),_ads.end());
778 }
779
780 /*!
781 **\brief Sets the angle of a torsion in OBTorsion
782 **\param radians the value to assign to the torsion
783 **\param index the index into the torsion of the OBTorsion
784 **\return boolean success
785 */
786 bool OBTorsion::SetAngle(double radians,unsigned int index)
787 {
788 if(index >= _ads.size())
789 return(false);
790
791 _ads[index].third = radians;
792
793 return(true);
794 }
795
796 /*!
797 **\brief Obtains the angle of a torsion in OBTorsion
798 **\param radians the value of the angle is set here
799 **\param index the index into the torsion of the OBTorsion
800 **\return boolean success
801 */
802 bool OBTorsion::GetAngle(double &radians, unsigned int index)
803 {
804 if(index >= _ads.size())
805 return false;
806 radians = _ads[index].third;
807 return true;
808 }
809
810 unsigned int OBTorsion::GetBondIdx()
811 {
812 return(_bc.first->GetBond(_bc.second)->GetIdx());
813 }
814
815 /*!
816 **\brief determines if torsion has only protons on either the a or d end
817 **\return boolean
818 */
819 bool OBTorsion::IsProtonRotor()
820 {
821 bool Aprotor = true;
822 bool Dprotor = true;
823 vector<triple<OBAtom*,OBAtom*,double> >::iterator ad;
824 for(ad = _ads.begin();ad != _ads.end() && (Aprotor || Dprotor);ad++)
825 {
826 if(!ad->first->IsHydrogen())
827 Aprotor = false;
828 if(!ad->second->IsHydrogen())
829 Dprotor = false;
830 }
831 return (Aprotor || Dprotor);
832 }
833
834 /*!
835 **\brief adds a new torsion to the OBTorsion object
836 */
837 bool OBTorsion::AddTorsion(OBAtom *a,OBAtom *b, OBAtom *c,OBAtom *d)
838 {
839 if(!Empty() && (b != _bc.first || c != _bc.second))
840 return(false);
841
842 if(Empty())
843 {
844 _bc.first = b;
845 _bc.second = c;
846 }
847
848 triple<OBAtom*,OBAtom*,double> ad(a,d,0.0);
849 _ads.push_back(ad);
850
851 return(true);
852 }
853
854 /*!
855 **\brief adds a new torsion to the OBTorsion object
856 */
857 bool OBTorsion::AddTorsion(quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> &atoms)
858 {
859 if(!Empty() && (atoms.second != _bc.first || atoms.third != _bc.second))
860 return(false);
861
862 if(Empty())
863 {
864 _bc.first = atoms.second;
865 _bc.second = atoms.third;
866 }
867
868 triple<OBAtom*,OBAtom*,double> ad(atoms.first,atoms.fourth,0.0);
869 _ads.push_back(ad);
870
871 return(true);
872 }
873
874 //\!brief OBTorsionData ctor
875 OBTorsionData::OBTorsionData()
876 {
877 _type = OBGenericDataType::TorsionData;
878 _attr = "TorsionData";
879 }
880
881 //
882 //member functions for OBTorsionData class - stores OBTorsion set
883 //
884 OBTorsionData::OBTorsionData(const OBTorsionData &src)
885 : OBGenericData(src), _torsions(src._torsions)
886 {
887 _type = OBGenericDataType::TorsionData;
888 _attr = "TorsionData";
889 }
890
891 OBTorsionData& OBTorsionData::operator =(const OBTorsionData &src)
892 {
893 if (this == &src)
894 return(*this);
895
896 OBGenericData::operator =(src);
897
898 _type = OBGenericDataType::TorsionData;
899 _attr = "TorsionData";
900 _torsions = src._torsions;
901
902 return(*this);
903 }
904
905 void OBTorsionData::Clear()
906 {
907 _torsions.clear();
908 }
909
910 void OBTorsionData::SetData(OBTorsion &torsion)
911 {
912 _torsions.push_back(torsion);
913 }
914
915 /*!
916 **\brief Fills a vector with the indices of the atoms in torsions (ordered abcd)
917 **\param torsions reference to the vector of abcd atom sets
918 **\return boolean success
919 */
920 bool OBTorsionData::FillTorsionArray(std::vector<std::vector<unsigned int> > &torsions)
921 {
922 if(_torsions.size() == 0)
923 return(false);
924
925 vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > tmpquads,quads;
926 vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> >::iterator thisQuad;
927 vector<OBTorsion>::iterator torsion;
928
929 //generate set of all 4 atom abcd's from torsion structure
930 for (torsion = _torsions.begin();torsion != _torsions.end();torsion++)
931 {
932 tmpquads = torsion->GetTorsions();
933 for(thisQuad = tmpquads.begin();thisQuad != tmpquads.end();thisQuad++)
934 quads.push_back(*thisQuad);
935 }
936
937 //fill array of torsion atoms
938
939 torsions.clear();
940 torsions.resize(quads.size());
941
942 unsigned int ct = 0;
943
944 for (thisQuad = quads.begin();thisQuad != quads.end();thisQuad++,ct++)
945 {
946 torsions[ct].resize(4);
947 torsions[ct][0] = thisQuad->first->GetIdx()-1;
948 torsions[ct][1] = thisQuad->second->GetIdx()-1;
949 torsions[ct][2] = thisQuad->third->GetIdx()-1;
950 torsions[ct][3] = thisQuad->fourth->GetIdx()-1;
951 }
952
953 return(true);
954 }
955
956 //
957 // Member functions for OBChiralDarta
958 //
959 bool OBChiralData::SetAtom4Refs(std::vector<unsigned int> atom4refs, atomreftype t)
960 {
961 if (atom4refs.size()>4)
962 {
963 obErrorLog.ThrowError(__func__, "More than 4 atoms in atom4refs", obDebug);
964 return(false);
965 }
966 switch(t){
967 case input: _atom4refs = atom4refs;break;
968 case output:_atom4refo = atom4refs;break;
969 case calcvolume:_atom4refc = atom4refs;break;
970 default:
971 obErrorLog.ThrowError(__func__, "AtomRefType called is invalid", obDebug);
972 return(false);
973 }
974 return (true);
975 }
976 int OBChiralData::AddAtomRef(unsigned int atomref, atomreftype t)
977 {
978 switch(t){
979 case input: _atom4refs.push_back(atomref);break;
980 case output: _atom4refo.push_back(atomref);break;
981 case calcvolume:_atom4refc.push_back(atomref);break;
982 default:
983 obErrorLog.ThrowError(__func__, "AtomRefType called is invalid", obDebug);
984 return(false);
985 }
986
987 return (_atom4refs.size());
988 }
989
990 unsigned int OBChiralData::GetAtomRef(int a, atomreftype t)
991 {
992 switch(t){
993 case input: return(_atom4refs[a]);break;
994 case output: return(_atom4refo[a]);break;
995 case calcvolume: return(_atom4refc[a]);break;
996 default:
997 obErrorLog.ThrowError(__func__, "AtomRefType called is invalid", obDebug);
998 return(false);
999 }
1000 }
1001 std::vector<unsigned int> OBChiralData::GetAtom4Refs(atomreftype t) const
1002 {
1003 switch (t){
1004 case output:
1005 return(_atom4refo);
1006 break;
1007 case input:
1008 return(_atom4refs);
1009 break;
1010 case calcvolume:
1011 return(_atom4refc);
1012 break;
1013 default:
1014 obErrorLog.ThrowError(__func__, "AtomRefType called is invalid", obDebug);
1015 return(_atom4refo);
1016 }
1017 }
1018
1019 unsigned int OBChiralData::GetSize(atomreftype t) const
1020 {
1021 switch (t)
1022 {
1023 case output:
1024 return(unsigned int)_atom4refo.size();
1025 break;
1026 case input:
1027 return(unsigned int)_atom4refs.size();
1028 break;
1029 case calcvolume:
1030 return(unsigned int)_atom4refc.size();
1031 default:
1032 obErrorLog.ThrowError(__func__, "AtomRefType called is invalid", obDebug);
1033 return(0);
1034 }
1035 }
1036
1037 OBChiralData::OBChiralData()
1038 {
1039 _type = OBGenericDataType::ChiralData;
1040 _attr = "ChiralData";
1041 }
1042
1043 OBChiralData::OBChiralData(const OBChiralData &src)
1044 : OBGenericData()
1045 {
1046 _atom4refs = src._atom4refs;
1047 _atom4refo = src._atom4refo;
1048 _atom4refc = src._atom4refc;
1049 parity=src.parity;
1050 }
1051
1052 OBChiralData & OBChiralData::operator=(const OBChiralData &src)
1053 {
1054 if(this == &src)
1055 return(*this);
1056
1057 _atom4refs = src._atom4refs;
1058 _atom4refo = src._atom4refo;
1059 _atom4refc = src._atom4refc;
1060 parity=src.parity;
1061 return(*this);
1062 }
1063
1064 void OBChiralData::Clear()
1065 {
1066 _atom4refs.clear();
1067 parity=0;
1068 _atom4refo.clear();
1069 _atom4refc.clear();
1070 }
1071
1072 } //end namespace OpenBabel
1073
1074 //! \file generic.cpp
1075 //! \brief Handle OBGenericData classes. Custom data for atoms, bonds, etc.