ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/generic.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 9 months ago) by tim
File size: 25198 byte(s)
Log Message:
adding openbabel

File Contents

# User Rev Content
1 tim 2440 /**********************************************************************
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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "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(__FUNCTION__, "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.