ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/residue.cpp
Revision: 2518
Committed: Fri Dec 16 21:52:50 2005 UTC (18 years, 7 months ago) by tim
File size: 46024 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

# User Rev Content
1 tim 2440 /**********************************************************************
2     residue.cpp - Handle macromolecule residues.
3    
4     Copyright (C) 2001, 2002 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     /**********************************************************************
21     Global arrays Residue, ElemDesc and function GetResidueNumber were
22     obtained in part or whole from RasMol2 by Roger Sayle.
23     ***********************************************************************/
24    
25     ///////////////////////////////////////////////////////////////////////////////
26     // File Includes
27     ///////////////////////////////////////////////////////////////////////////////
28    
29 gezelter 2450 #include "config.h"
30 tim 2440
31     #if HAVE_IOSTREAM
32     #include <iostream>
33     #elif HAVE_IOSTREAM_H
34     #include <iostream.h>
35     #endif
36    
37     #if HAVE_FSTREAM
38     #include <fstream>
39     #elif HAVE_FSTREAM_H
40     #include <fstream.h>
41     #endif
42    
43     #include "mol.hpp"
44     #include "bitvec.hpp"
45    
46     using namespace std;
47    
48     namespace OpenBabel
49     {
50     /** \class OBResidue
51     \brief Residue information
52    
53     The residue information is drawn from PDB or MOL2 files (or similar), which
54     track biomolecule information,
55     and are stored in the OBResidue class. OBResidues are stored inside the
56     OBAtom class and OBMol classes.
57     The residue information for an atom can be requested in
58     the following way:
59     \code
60     OBAtom *atom;
61     OBResidue *r;
62     atom = mol.GetAtom(1);
63     r = atom->GetResidue();
64     \endcode
65     The residue information for a molecule can be manipulated too:
66     \code
67     cout << "This molecule has " << mol.NumResidues() << " residues." << endl;
68     OBResidue *r;
69     r = mol.GetResidue(1);
70     \endcode
71     */
72    
73     ///////////////////////////////////////////////////////////////////////////////
74     // Global Definitions
75     ///////////////////////////////////////////////////////////////////////////////
76    
77     #define MAXSETNO 40
78     #define MAXELEM 1024
79     #define MINELEM 29
80     #define MAXRES 100
81     #define MINRES 54
82    
83     ///////////////////////////////////////////////////////////////////////////////
84     // Amino Acid Definitions
85     ///////////////////////////////////////////////////////////////////////////////
86    
87     #define AA_ALA (1<<1)
88     #define AA_GLY (1<<2)
89     #define AA_LEU (1<<3)
90     #define AA_SER (1<<4)
91     #define AA_VAL (1<<5)
92     #define AA_THR (1<<6)
93     #define AA_LYS (1<<7)
94     #define AA_ASP (1<<8)
95     #define AA_ILE (1<<9)
96     #define AA_ASN (1<<10)
97     #define AA_GLU (1<<11)
98     #define AA_PRO (1<<12)
99     #define AA_ARG (1<<13)
100     #define AA_PHE (1<<14)
101     #define AA_GLN (1<<15)
102     #define AA_TYR (1<<16)
103     #define AA_HIS (1<<17)
104     #define AA_CYS (1<<18)
105     #define AA_MET (1<<19)
106     #define AA_TRP (1<<20)
107    
108     //! Residue property definitions
109     namespace OBAminoAcidProperty
110     {
111     static const unsigned int ACIDIC = 0;
112     static const unsigned int ACYCLIC = 1;
113     static const unsigned int ALIPHATIC = 2;
114     static const unsigned int AROMATIC = 3;
115     static const unsigned int BASIC = 4;
116     static const unsigned int BURIED = 5;
117     static const unsigned int CHARGED = 6;
118     static const unsigned int CYCLIC = 7;
119     static const unsigned int HYDROPHOBIC = 8;
120     static const unsigned int LARGE = 9;
121     static const unsigned int MEDIUM = 10;
122     static const unsigned int NEGATIVE = 11;
123     static const unsigned int NEUTRAL = 12;
124     static const unsigned int POLAR = 13;
125     static const unsigned int POSITIVE = 14;
126     static const unsigned int SMALL = 15;
127     static const unsigned int SURFACE = 16;
128     }
129    
130     //! Residue atom properties
131     namespace OBResidueAtomProperty
132     {
133     static const unsigned int ALPHA_CARBON = 0;
134     static const unsigned int AMINO_BACKBONE = 1;
135     static const unsigned int BACKBONE = 2;
136     static const unsigned int CYSTEINE_SULPHUR = 3;
137     static const unsigned int LIGAND = 4;
138     static const unsigned int NUCLEIC_BACKBONE = 5;
139     static const unsigned int SHAPELY_BACKBONE = 6;
140     static const unsigned int SHAPELY_SPECIAL = 7;
141     static const unsigned int SIDECHAIN = 8;
142     static const unsigned int SUGAR_PHOSPHATE = 9;
143     }
144     /// Residue names
145     namespace OBResidueIndex
146     {
147     static const unsigned int ALA = 0;
148     static const unsigned int GLY = 1;
149     static const unsigned int LEU = 2;
150     static const unsigned int SER = 3;
151     static const unsigned int VAL = 4;
152     static const unsigned int THR = 5;
153     static const unsigned int LYS = 6;
154     static const unsigned int ASP = 7;
155     static const unsigned int ILE = 8;
156     static const unsigned int ASN = 9;
157     static const unsigned int GLU = 10;
158     static const unsigned int PRO = 11;
159     static const unsigned int ARG = 12;
160     static const unsigned int PHE = 13;
161     static const unsigned int GLN = 14;
162     static const unsigned int TYR = 15;
163     static const unsigned int HIS = 16;
164     static const unsigned int CYS = 17;
165     static const unsigned int MET = 18;
166     static const unsigned int TRP = 19;
167     static const unsigned int ASX = 20;
168     static const unsigned int GLX = 21;
169     static const unsigned int PCA = 22;
170     static const unsigned int HYP = 23;
171     static const unsigned int A = 24;
172     static const unsigned int C = 25;
173     static const unsigned int G = 26;
174     static const unsigned int T = 27;
175     static const unsigned int U = 28;
176     static const unsigned int UPLUS = 29;
177     static const unsigned int I = 30;
178     //static const unsigned int _1MA = 31;
179     //static const unsigned int _5MC = 32;
180     static const unsigned int OMC = 33;
181     //static const unsigned int _1MG = 34;
182     //static const unsigned int _2MG = 35;
183     static const unsigned int M2G = 36;
184     //static const unsigned int _7MG = 37;
185     static const unsigned int OMG = 38;
186     static const unsigned int YG = 39;
187     static const unsigned int H2U = 40;
188     //static const unsigned int _5MU = 41;
189     static const unsigned int PSU = 42;
190     static const unsigned int UNK = 43;
191     static const unsigned int ACE = 44;
192     static const unsigned int FOR = 45;
193     static const unsigned int HOH = 46;
194     static const unsigned int DOD = 47;
195     static const unsigned int SO4 = 48;
196     static const unsigned int PO4 = 49;
197     static const unsigned int NAD = 50;
198     static const unsigned int COA = 51;
199     static const unsigned int NAP = 52;
200     static const unsigned int NDP = 53;
201     }
202     /// Residue types.
203     namespace OBResidueProperty
204     {
205     static const unsigned int AMINO = 0;
206     static const unsigned int AMINO_NUCLEO = 1;
207     static const unsigned int COENZYME = 2;
208     static const unsigned int ION = 3;
209     static const unsigned int NUCLEO = 4;
210     static const unsigned int PROTEIN = 5;
211     static const unsigned int PURINE = 6;
212     static const unsigned int PYRIMIDINE = 7;
213     static const unsigned int SOLVENT = 8;
214     static const unsigned int WATER = 9;
215     }
216    
217     ///////////////////////////////////////////////////////////////////////////////
218     // Amino Acid Property Definitions
219     ///////////////////////////////////////////////////////////////////////////////
220    
221     #define IS_ACIDIC(x) ((x) & ((AA_ASP)|(AA_GLU)))
222     #define IS_ACYCLIC(x) ((x) & ((AA_ALA)|(AA_GLY)|(AA_LEU)|(AA_SER)| \
223     (AA_VAL)|(AA_THR)|(AA_LYS)|(AA_ASP)| \
224     (AA_ILE)|(AA_ASN)|(AA_GLU)|(AA_GLN)| \
225     (AA_CYS)|(AA_MET)))
226     #define IS_ALIPHATIC(x) ((x) & ((AA_ALA)|(AA_GLY)|(AA_ILE)|(AA_LEU)| \
227     (AA_VAL)))
228     #define IS_AROMATIC(x) ((x) & ((AA_HIS)|(AA_PHE)|(AA_TRP)|(AA_TYR)))
229     #define IS_BASIC(x) ((x) & ((AA_ARG)|(AA_HIS)|(AA_LYS)))
230     #define IS_BURIED(x) ((x) & ((AA_ALA)|(AA_CYS)|(AA_ILE)|(AA_LEU)| \
231     (AA_MET)|(AA_PHE)|(AA_TRP)|(AA_VAL)))
232     #define IS_CHARGED(x) ((x) & ((AA_ASP)|(AA_GLU)|(AA_ARG)|(AA_HIS)| \
233     (AA_LYS)))
234     #define IS_CYCLIC(x) ((x) & ((AA_HIS)|(AA_PHE)|(AA_PRO)|(AA_TRP)| \
235     (AA_TYR)))
236     #define IS_HYDROPHOBIC(x) ((x) & ((AA_ALA)|(AA_LEU)|(AA_VAL)|(AA_ILE)| \
237     (AA_PRO)|(AA_PHE)|(AA_MET)|(AA_TRP)))
238     #define IS_LARGE(x) ((x) & ((AA_ARG)|(AA_PHE)|(AA_GLN)|(AA_TYR)| \
239     (AA_HIS)|(AA_LEU)|(AA_LYS)|(AA_ILE)| \
240     (AA_GLU)|(AA_MET)|(AA_TRP)))
241     #define IS_MEDIUM(x) ((x) & ((AA_VAL)|(AA_THR)|(AA_ASP)|(AA_ASN)| \
242     (AA_PRO)|(AA_CYS)))
243     #define IS_NEGATIVE(x) ((x) & ((AA_ASP)|(AA_GLU)))
244     #define IS_NEUTRAL(x) ((x) & ((AA_ALA)|(AA_GLY)|(AA_LEU)|(AA_SER)| \
245     (AA_VAL)|(AA_THR)|(AA_PHE)|(AA_GLN)| \
246     (AA_TYR)|(AA_HIS)|(AA_CYS)|(AA_MET)| \
247     (AA_TRP)|(AA_ILE)|(AA_ASN)|(AA_PRO)))
248     #define IS_POLAR(x) ((x) & ((AA_ASP)|(AA_ILE)|(AA_ASN)|(AA_GLU)| \
249     (AA_SER)|(AA_THR)|(AA_ARG)|(AA_GLN)| \
250     (AA_CYS)|(AA_HIS)))
251     #define IS_POSITIVE(x) ((x) & ((AA_ARG)|(AA_HIS)|(AA_LYS)))
252     #define IS_SMALL(x) ((x) & ((AA_ALA)|(AA_GLY)|(AA_SER)))
253     #define IS_SURFACE(x) ((x) & ((AA_THR)|(AA_LYS)|(AA_ASP)|(AA_ILE)| \
254     (AA_ASN)|(AA_GLU)|(AA_PRO)|(AA_ARG)| \
255     (AA_GLY)|(AA_SER)|(AA_GLN)|(AA_TYR)| \
256     (AA_HIS)))
257    
258     ////////////////////////////////////////////////////////////////////////////////
259     // Global Variables
260     ////////////////////////////////////////////////////////////////////////////////
261    
262     static char Residue[MAXRES][4] = {
263     /*===============*/
264     /* Amino Acids */
265     /*===============*/
266    
267     /* Ordered by Cumulative Frequency in Brookhaven *
268     * Protein Databank, December 1991 */
269    
270     "ALA", /* 8.4% */ "GLY", /* 8.3% */
271     "LEU", /* 8.0% */ "SER", /* 7.5% */
272     "VAL", /* 7.1% */ "THR", /* 6.4% */
273     "LYS", /* 5.8% */ "ASP", /* 5.5% */
274     "ILE", /* 5.2% */ "ASN", /* 4.9% */
275     "GLU", /* 4.9% */ "PRO", /* 4.4% */
276     "ARG", /* 3.8% */ "PHE", /* 3.7% */
277     "GLN", /* 3.5% */ "TYR", /* 3.5% */
278     "HIS", /* 2.3% */ "CYS", /* 2.0% */
279     "MET", /* 1.8% */ "TRP", /* 1.4% */
280    
281     "ASX", "GLX", "PCA", "HYP",
282    
283     /*===================*/
284     /* DNA Nucleotides */
285     /*===================*/
286     " A", " C", " G", " T",
287    
288     /*===================*/
289     /* RNA Nucleotides */
290     /*===================*/
291     " U", " +U", " I", "1MA",
292     "5MC", "OMC", "1MG", "2MG",
293     "M2G", "7MG", "OMG", " YG",
294     "H2U", "5MU", "PSU",
295    
296     /*=================*/
297     /* Miscellaneous */
298     /*=================*/
299     "UNK", "ACE", "FOR", "HOH",
300     "DOD", "SO4", "PO4", "NAD",
301     "COA", "NAP", "NDP"
302     };
303    
304     /* Avoid SGI Compiler Warnings! */
305     static char ElemDesc[MAXELEM][4] = {
306     { ' ', 'N', ' ', ' ' }, /* 0*/
307     { ' ', 'C', 'A', ' ' }, /* 1*/
308     { ' ', 'C', ' ', ' ' }, /* 2*/
309     { ' ', 'O', ' ', ' ' }, /* 3*/ /* 0-3 Amino Acid Backbone */
310     { ' ', 'C', '\'', ' ' }, /* 4*/
311     { ' ', 'O', 'T', ' ' }, /* 5*/
312     { ' ', 'S', ' ', ' ' }, /* 6*/
313     { ' ', 'P', ' ', ' ' }, /* 7*/ /* 4-7 Shapely Amino Backbone */
314     { ' ', 'O', '1', 'P' }, /* 8*/
315     { ' ', 'O', '2', 'P' }, /* 9*/
316     { ' ', 'O', '5', '*' }, /*10*/
317     { ' ', 'C', '5', '*' }, /*11*/
318     { ' ', 'C', '4', '*' }, /*12*/
319     { ' ', 'O', '4', '*' }, /*13*/
320     { ' ', 'C', '3', '*' }, /*14*/
321     { ' ', 'O', '3', '*' }, /*15*/
322     { ' ', 'C', '2', '*' }, /*16*/
323     { ' ', 'O', '2', '*' }, /*17*/
324     { ' ', 'C', '1', '*' }, /*18*/ /* 7-18 Nucleic Acid Backbone */
325     { ' ', 'C', 'A', '2' }, /*19*/ /* 19 Shapely Special */
326     { ' ', 'S', 'G', ' ' }, /*20*/ /* 20 Cysteine Sulphur */
327     { ' ', 'N', '1', ' ' }, /*21*/
328     { ' ', 'N', '2', ' ' }, /*22*/
329     { ' ', 'N', '3', ' ' }, /*23*/
330     { ' ', 'N', '4', ' ' }, /*24*/
331     { ' ', 'N', '6', ' ' }, /*25*/
332     { ' ', 'O', '2', ' ' }, /*26*/
333     { ' ', 'O', '4', ' ' }, /*27*/
334     { ' ', 'O', '6', ' ' } /*28*/ /* 21-28 Nucleic Acid H-Bonding */
335     };
336    
337     static unsigned int ResNo = MINRES;
338     static unsigned int ElemNo = MINELEM;
339    
340     ///////////////////////////////////////////////////////////////////////////////
341     // Residue Functions
342     ///////////////////////////////////////////////////////////////////////////////
343    
344     static unsigned int GetAtomIDNumber(const char *atomid)
345     {
346     if (atomid != NULL)
347     {
348     int ch1 = toupper(atomid[0]);
349     int ch2 = toupper(atomid[1]);
350     int ch3 = toupper(atomid[2]);
351     int ch4 = toupper(atomid[3]);
352    
353     if (ch1 == ' ')
354     {
355     switch(ch2)
356     {
357     case 'C':
358    
359     switch(ch3)
360     {
361     case 'A':
362    
363     if (ch4 == ' ')
364     return 1;
365     else if (ch4 == '2')
366     return 19;
367    
368     break;
369    
370     case ' ':
371     if (ch4 == ' ')
372     return 2;
373     break;
374    
375     case '\'':
376     if (ch4 == ' ')
377     return 4;
378     break;
379    
380     case '1':
381     if (ch4 == '*')
382     return 18;
383     break;
384    
385     case '2':
386     if (ch4 == '*')
387     return 16;
388     break;
389    
390     case '3':
391     if (ch4 == '*')
392     return 14;
393     break;
394    
395     case '4':
396     if (ch4 == '*')
397     return 12;
398     break;
399    
400     case '5':
401     if (ch4 == '*')
402     return 11;
403     break;
404    
405     }
406    
407     break;
408    
409     case 'N':
410    
411     if (ch4 == ' ')
412     {
413     switch (ch3)
414     {
415     case ' ':
416     return 0;
417     case '1':
418     return 21;
419     case '2':
420     return 22;
421     case '3':
422     return 23;
423     case '4':
424     return 24;
425     case '6':
426     return 25;
427     }
428     }
429    
430     break;
431    
432     case 'O':
433    
434     switch(ch3)
435     {
436     case ' ':
437    
438     if (ch4 == ' ')
439     return 3;
440    
441     break;
442    
443     case 'T':
444    
445     if (ch4 == ' ')
446     return 5;
447    
448     break;
449    
450     case '1':
451    
452     if (ch4 == 'P')
453     return 8;
454    
455     break;
456    
457     case '2':
458    
459     if (ch4 == 'P')
460     return 9;
461     else if (ch4 == '*')
462     return 17;
463     else if (ch4 == ' ')
464     return 26;
465    
466     break;
467    
468     case '3':
469    
470     if (ch4 == '*')
471     return 15;
472    
473     break;
474    
475     case '4':
476    
477     if (ch4 == '*')
478     return 13;
479     else if (ch4 == ' ')
480     return 27;
481    
482     break;
483    
484     case '5':
485    
486     if (ch4 == '*')
487     return 10;
488    
489     break;
490    
491     case '6':
492    
493     if (ch4 == ' ')
494     return 28;
495    
496     break;
497     }
498    
499     break;
500    
501     case 'P':
502    
503     if ((ch3 == ' ') && (ch4 == ' '))
504     return 7;
505    
506     break;
507    
508     case 'S':
509    
510     if (ch4 == ' ')
511     {
512     if (ch3 == ' ')
513     return 6;
514     else if (ch3 == 'G')
515     return 20;
516     }
517    
518     break;
519     }
520     }
521    
522     unsigned int refno;
523     for( refno = MINELEM ; refno < ElemNo ; refno++ )
524     if( !strncmp(ElemDesc[refno], atomid, 4) )
525     return refno;
526    
527     if ( ElemNo < MAXELEM - 1 )
528     {
529     ElemNo++;
530     ElemDesc[refno][0] = (char) ch1;
531     ElemDesc[refno][1] = (char) ch2;
532     ElemDesc[refno][2] = (char) ch3;
533     ElemDesc[refno][3] = (char) ch4;
534     return refno;
535     }
536     else
537     {
538 tim 2518 obErrorLog.ThrowError(__func__, "Maximum number of atom ids exceeded", obWarning);
539 tim 2440 return 0;
540     }
541     }
542     else
543     {
544 tim 2518 obErrorLog.ThrowError(__func__, "NULL Atom IDs specified", obWarning);
545 tim 2440 return 0;
546     }
547     }
548    
549     static unsigned int GetResidueNumber(const char *res)
550     {
551     if (res != NULL)
552     {
553     int ch1 = toupper(res[0]);
554     int ch2 = toupper(res[1]);
555     int ch3 = toupper(res[2]);
556    
557     switch( ch1 )
558     {
559     case(' '):
560    
561     if( ch2 == ' ' )
562     {
563     switch( ch3 )
564     {
565     case('A'): return( 24 );
566     case('C'): return( 25 );
567     case('G'): return( 26 );
568     case('T'): return( 27 );
569     case('U'): return( 28 );
570     case('I'): return( 30 );
571     }
572     }
573     else if( ch2 == '+' )
574     {
575     if( ch3 == 'U' )
576     return( 29 );
577     }
578     else if( ch2 == 'Y' )
579     {
580     if( ch3 == 'G' )
581     return( 39 );
582     }
583    
584     break;
585    
586     case('0'):
587    
588     if( ch2 == 'M' )
589     {
590     if( ch3 == 'C' )
591     return( 33 );
592     else if( ch3 == 'G' )
593     return( 38 );
594     }
595    
596     break;
597    
598     case('1'):
599    
600     if( ch2 == 'M' )
601     {
602     if( ch3 == 'A' )
603     return( 31 );
604     else if( ch3 == 'G' )
605     return( 34 );
606     }
607    
608     break;
609    
610     case('2'):
611    
612     if( ch2 == 'M' )
613     if( ch3 == 'G' )
614     return( 35 );
615    
616     break;
617    
618     case('5'):
619    
620     if( ch2 == 'M' )
621     {
622     if( ch3 == 'C' )
623     return( 32 );
624     else if( ch3 == 'U' )
625     return( 41 );
626     }
627    
628     break;
629    
630     case('7'):
631    
632     if( ch2 == 'M' )
633     if( ch3 == 'G' )
634     return( 37 );
635    
636     break;
637    
638     case('A'):
639    
640     if( ch2 == 'L' )
641     {
642     if( ch3 == 'A' )
643     return( 0 );
644     }
645     else if( ch2 == 'S' )
646     {
647     if( ch3 == 'P' )
648     return( 7 );
649     else if( ch3 == 'N' )
650     return( 9 );
651     else if( ch3 == 'X' )
652     return( 20 );
653     }
654     else if( ch2 == 'R' )
655     {
656     if( ch3 == 'G' )
657     return( 12 );
658     }
659     else if( ch2 == 'C' )
660     {
661     if( ch3 == 'E' )
662     return( 44 );
663     }
664     else if( ch2 == 'D' )
665     {
666     if( ch3 == 'E' )
667     return( 24 ); /* "ADE" -> " A" */
668     }
669    
670     break;
671    
672     case('C'):
673    
674     if( ch2 == 'Y' )
675     {
676     if( ch3 == 'S' )
677     return( 17 );
678     else if( ch3 == 'H' )
679     return( 17 ); /* "CYH" -> "CYS" */
680     else if( ch3 == 'T' )
681     return( 25 ); /* "CYT" -> " C" */
682     }
683     else if( ch2 == 'O' )
684     {
685     if( ch3 == 'A' )
686     return( 51 );
687     }
688     else if( ch2 == 'P' )
689     {
690     if( ch3 == 'R' )
691     return( 11 ); /* "CPR" -> "PRO" */
692     }
693     else if( ch2 == 'S' )
694     {
695     if( ch3 == 'H' )
696     return( 17 ); /* "CSH" -> "CYS" */
697     else if( ch3 == 'M' )
698     return( 17 ); /* "CSM" -> "CYS" */
699     }
700    
701     break;
702    
703     case('D'):
704    
705     if( ch2 == 'O' )
706     {
707     if( ch3 == 'D' )
708     return( 47 );
709     }
710     else if( ch2 == '2' )
711     {
712     if( ch3 == 'O' )
713     return( 47 ); /* "D2O" -> "DOD" */
714     }
715    
716     break;
717    
718     case('F'):
719    
720     if( ch2 == 'O' )
721     if( ch3 == 'R' )
722     return( 45 );
723    
724     break;
725    
726     case('G'):
727    
728     if( ch2 == 'L' )
729     {
730     if( ch3 == 'Y' )
731     return( 1 );
732     else if( ch3 == 'U' )
733     return( 10 );
734     else if( ch3 == 'N' )
735     return( 14 );
736     else if( ch3 == 'X' )
737     return( 21 );
738     }
739     else if( ch2 == 'U' )
740     {
741     if( ch3 == 'A' )
742     return( 26 ); /* "GUA" -> " G" */
743     }
744    
745     break;
746    
747     case('H'):
748    
749     if( ch2 == 'I' )
750     {
751     if( ch3 == 'S' )
752     return( 16 );
753     }
754     else if( ch2 == 'O' )
755     {
756     if( ch3 == 'H' )
757     return( 46 );
758     }
759     else if( ch2 == 'Y' )
760     {
761     if( ch3 == 'P' )
762     return( 23 );
763     }
764     else if( ch2 == '2' )
765     {
766     if( ch3 == 'O' )
767     return( 46 ); /* "H20" -> "HOH" */
768     else if( ch3 == 'U' )
769     return( 40 );
770     }
771    
772     break;
773    
774     case('I'):
775    
776     if( ch2 == 'L' )
777     if( ch3 == 'E' )
778     return( 8 );
779    
780     break;
781    
782     case('L'):
783    
784     if( ch2 == 'E' )
785     {
786     if( ch3 == 'U' )
787     return( 2 );
788     }
789     else if( ch2 == 'Y' )
790     {
791     if( ch3 == 'S' )
792     return( 6 );
793     }
794    
795     break;
796    
797     case('M'):
798    
799     if( ch2 == 'E' )
800     {
801     if( ch3 == 'T' )
802     return( 18 );
803     }
804     else if( ch2 == '2' )
805     {
806     if( ch3 == 'G' )
807     return( 36 );
808     }
809    
810     break;
811    
812     case('N'):
813    
814     if( ch2 == 'A' )
815     {
816     if( ch3 == 'D' )
817     return( 50 );
818     else if( ch3 == 'P' )
819     return( 52 );
820     }
821     else if( ch2 == 'D' )
822     {
823     if( ch3 == 'P' )
824     return( 53 );
825     }
826    
827     break;
828    
829     case('P'):
830    
831     if( ch2 == 'R' )
832     {
833     if( ch3 == 'O' )
834     return( 11 );
835     }
836     else if( ch2 == 'H' )
837     {
838     if( ch3 == 'E' )
839     return( 13 );
840     }
841     else if( ch2 == 'C' )
842     {
843     if( ch3 == 'A' )
844     return( 22 );
845     }
846     else if( ch2 == 'O' )
847     {
848     if( ch3 == '4' )
849     return( 49 );
850     }
851     else if( ch2 == 'S' )
852     {
853     if( ch3 == 'U' )
854     return( 42 );
855     }
856    
857     break;
858    
859     case('S'):
860    
861     if( ch2 == 'E' )
862     {
863     if( ch3 == 'R' )
864     return( 3 );
865     }
866     else if( ch2 == 'O' )
867     {
868     if( ch3 == '4' )
869     return( 48 );
870     else if( ch3 == 'L' )
871     return( 46 ); /* "SOL" -> "HOH" */
872     }
873     else if( ch2 == 'U' )
874     {
875     if( ch3 == 'L' )
876     return( 48 ); /* "SUL" -> "SO4" */
877     }
878    
879     break;
880    
881     case('T'):
882    
883     if( ch2 == 'H' )
884     {
885     if( ch3 == 'R' )
886     return( 5 );
887     else if( ch3 == 'Y' )
888     return( 27 ); /* "THY" -> " T" */
889     }
890     else if( ch2 == 'Y' )
891     {
892     if( ch3 == 'R' )
893     return( 15 );
894     }
895     else if( ch2 == 'R' )
896     {
897     if( ch3 == 'P' )
898     return( 19 );
899     else if( ch3 == 'Y' )
900     return( 19 ); /* "TRY" -> "TRP" */
901     }
902     else if( ch2 == 'I' )
903     {
904     if( ch3 == 'P' )
905     return( 46 ); /* "TIP" -> "HOH" */
906     }
907    
908     break;
909    
910     case('U'):
911    
912     if( ch2 == 'N' )
913     {
914     if( ch3 == 'K' )
915     return( 43 );
916     }
917     else if( ch2 == 'R' )
918     {
919     if( ch3 == 'A' )
920     return( 28 ); /* "URA" -> " U" */
921     else if( ch3 == 'I' )
922     return( 28 ); /* "URI" -> " U" */
923     }
924    
925     break;
926    
927     case('V'):
928    
929     if( ch2 == 'A' )
930     if( ch3 == 'L' )
931     return( 4 );
932    
933     break;
934    
935     case('W'):
936    
937     if( ch2 == 'A' )
938     if( ch3 == 'T' )
939     return( 46 ); /* "WAT" -> "HOH" */
940    
941     break;
942     }
943    
944     unsigned int refno;
945     for( refno = MINRES; refno < ResNo ; refno++ )
946     if( !strncmp(Residue[refno],res,3) )
947     return refno;
948    
949     if ( ResNo < MAXRES - 1 )
950     {
951     ResNo++;
952     Residue[refno][0] = (char) ch1;
953     Residue[refno][1] = (char) ch2;
954     Residue[refno][2] = (char) ch3;
955     return refno;
956     }
957     }
958    
959     return OBResidueIndex::UNK;
960     }
961    
962     static void SetResidueKeys(const char *residue,
963     unsigned int &reskey,
964     unsigned int &aakey)
965     {
966     reskey = GetResidueNumber(residue);
967     switch(reskey)
968     {
969     case OBResidueIndex::ALA:
970     aakey = AA_ALA;
971     break;
972     case OBResidueIndex::GLY:
973     aakey = AA_GLY;
974     break;
975     case OBResidueIndex::LEU:
976     aakey = AA_LEU;
977     break;
978     case OBResidueIndex::SER:
979     aakey = AA_SER;
980     break;
981     case OBResidueIndex::VAL:
982     aakey = AA_VAL;
983     break;
984     case OBResidueIndex::THR:
985     aakey = AA_THR;
986     break;
987     case OBResidueIndex::LYS:
988     aakey = AA_LYS;
989     break;
990     case OBResidueIndex::ASP:
991     aakey = AA_ASP;
992     break;
993     case OBResidueIndex::ILE:
994     aakey = AA_ILE;
995     break;
996     case OBResidueIndex::ASN:
997     aakey = AA_ASN;
998     break;
999     case OBResidueIndex::GLU:
1000     aakey = AA_GLU;
1001     break;
1002     case OBResidueIndex::PRO:
1003     aakey = AA_PRO;
1004     break;
1005     case OBResidueIndex::ARG:
1006     aakey = AA_ARG;
1007     break;
1008     case OBResidueIndex::PHE:
1009     aakey = AA_PHE;
1010     break;
1011     case OBResidueIndex::GLN:
1012     aakey = AA_GLN;
1013     break;
1014     case OBResidueIndex::TYR:
1015     aakey = AA_TYR;
1016     break;
1017     case OBResidueIndex::HIS:
1018     aakey = AA_HIS;
1019     break;
1020     case OBResidueIndex::CYS:
1021     aakey = AA_CYS;
1022     break;
1023     case OBResidueIndex::MET:
1024     aakey = AA_MET;
1025     break;
1026     case OBResidueIndex::TRP:
1027     aakey = AA_TRP;
1028     break;
1029     default:
1030     aakey = 0;
1031     break;
1032     }
1033     }
1034    
1035     ///////////////////////////////////////////////////////////////////////////////
1036     // OBResidue: Constructors / Destructor
1037     ///////////////////////////////////////////////////////////////////////////////
1038    
1039     OBResidue::OBResidue()
1040     {
1041     _chain = 'A';
1042     _idx = 0;
1043     _aakey = 0;
1044     _reskey = OBResidueIndex::UNK;
1045     _resnum = 0;
1046     _resname = "";
1047     _vdata.clear();
1048     }
1049    
1050     OBResidue::OBResidue(const OBResidue &src)
1051     // Currently does not copy vdata information
1052     {
1053     _chain = src._chain;
1054     _aakey = src._aakey;
1055     _reskey = src._reskey;
1056     _resnum = src._resnum;
1057     _resname = src._resname;
1058     _atomid = src._atomid;
1059     _hetatm = src._hetatm;
1060     _sernum = src._sernum;
1061     }
1062    
1063     OBResidue::~OBResidue()
1064     {
1065     vector<OBAtom*>::iterator a;
1066     for ( a = _atoms.begin() ; a != _atoms.end() ; a++ )
1067     (*a)->SetResidue(NULL);
1068     _atoms.clear();
1069     if (!_vdata.empty())
1070     {
1071     vector<OBGenericData*>::iterator m;
1072     for (m = _vdata.begin();m != _vdata.end();m++)
1073     delete *m;
1074     _vdata.clear();
1075     }
1076     }
1077    
1078     ///////////////////////////////////////////////////////////////////////////////
1079     // OBResidue: Operator Overloads
1080     ///////////////////////////////////////////////////////////////////////////////
1081    
1082     OBResidue &OBResidue::operator = (const OBResidue &src)
1083     //copy residue information
1084     // Currently does not copy vdata informtion
1085     {
1086     if (this != &src)
1087     {
1088     _chain = src._chain;
1089     _aakey = src._aakey;
1090     _reskey = src._reskey;
1091     _resnum = src._resnum;
1092     _resname = src._resname;
1093     _atomid = src._atomid;
1094     _hetatm = src._hetatm;
1095     _sernum = src._sernum;
1096     }
1097    
1098     return(*this);
1099     }
1100    
1101     ///////////////////////////////////////////////////////////////////////////////
1102     // OBResidue: Data Access / Manipulation
1103     ///////////////////////////////////////////////////////////////////////////////
1104    
1105     void OBResidue::AddAtom(OBAtom *atom)
1106     {
1107     if (atom != NULL)
1108     {
1109     atom->SetResidue(this);
1110    
1111     _atoms.push_back(atom);
1112     _atomid.push_back("");
1113     _hetatm.push_back(false);
1114     _sernum.push_back(0);
1115     }
1116     }
1117    
1118     void OBResidue::InsertAtom(OBAtom *atom)
1119     {
1120     if (atom != NULL)
1121     {
1122     atom->SetResidue(this);
1123    
1124     _atoms.push_back(atom);
1125     _atomid.push_back("");
1126     _hetatm.push_back(false);
1127     _sernum.push_back(0);
1128     }
1129     }
1130    
1131     void OBResidue::RemoveAtom(OBAtom *atom)
1132     {
1133     if (atom != NULL)
1134     {
1135     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1136     {
1137     if (_atoms[i] == atom)
1138     {
1139     atom->SetResidue(NULL);
1140     _atoms.erase(_atoms.begin() + i);
1141     _atomid.erase(_atomid.begin() + i);
1142     _hetatm.erase(_hetatm.begin() + i);
1143     _sernum.erase(_sernum.begin() + i);
1144     }
1145     }
1146     }
1147     }
1148    
1149     void OBResidue::Clear(void)
1150     {
1151     for (unsigned int i = 0 ; i < _atoms.size() ; i++ )
1152     _atoms[i]->SetResidue(NULL);
1153    
1154     _chain = 'A';
1155     _idx = 0;
1156     _aakey = 0;
1157     _reskey = OBResidueIndex::UNK;
1158     _resnum = 0;
1159     _resname = "";
1160    
1161     _atoms.clear();
1162     _atomid.clear();
1163     _hetatm.clear();
1164     _sernum.clear();
1165     }
1166    
1167     void OBResidue::SetChain(char chain)
1168     {
1169     _chain = chain;
1170     }
1171    
1172     void OBResidue::SetChainNum(unsigned int chainnum)
1173     {
1174     _chain = (char) ('A' + chainnum - 1);
1175     }
1176    
1177     void OBResidue::SetIdx(unsigned int idx)
1178     {
1179     _idx = idx;
1180     }
1181    
1182     void OBResidue::SetName(const string &name)
1183     {
1184     _resname = name;
1185     SetResidueKeys(_resname.c_str(), _reskey, _aakey);
1186     }
1187    
1188     void OBResidue::SetNum(unsigned int resnum)
1189     {
1190     _resnum = resnum;
1191     }
1192    
1193     void OBResidue::SetAtomID(OBAtom *atom, const string &id)
1194     {
1195     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1196     if (_atoms[i] == atom)
1197     _atomid[i] = id;
1198     }
1199    
1200     void OBResidue::SetHetAtom(OBAtom *atom, bool hetatm)
1201     {
1202     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1203     if (_atoms[i] == atom)
1204     _hetatm[i] = hetatm;
1205     }
1206    
1207     void OBResidue::SetSerialNum(OBAtom *atom, unsigned int sernum)
1208     {
1209     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1210     if (_atoms[i] == atom)
1211     _sernum[i] = sernum;
1212     }
1213    
1214     vector<OBAtom*> OBResidue::GetAtoms(void) const
1215     {
1216     return _atoms;
1217     }
1218    
1219     vector<OBBond*> OBResidue::GetBonds(bool exterior) const
1220     {
1221     OBAtom *atom;
1222     vector<OBBond*> bonds;
1223     OBBitVec idxs;
1224     unsigned int sz;
1225    
1226     sz = (unsigned int) _atoms.size();
1227     for ( unsigned int i = 0 ; i < sz ; i++ )
1228     {
1229     atom = _atoms[i];
1230     OBBond *bond;
1231     vector<OBEdgeBase*>::iterator b;
1232     for (bond = atom->BeginBond(b) ; bond ; bond = atom->NextBond(b))
1233     {
1234     if (!idxs.BitIsOn(bond->GetIdx()))
1235     {
1236     if (!exterior)
1237     {
1238     if (bond->GetNbrAtom(atom)->GetResidue() == this)
1239     bonds.push_back(&(*bond));
1240     }
1241     else
1242     bonds.push_back(&(*bond));
1243    
1244     idxs.SetBitOn(bond->GetIdx());
1245     }
1246     }
1247     }
1248    
1249     return bonds;
1250     }
1251    
1252     string OBResidue::GetName(void) const
1253     {
1254     return _resname;
1255     }
1256    
1257     unsigned int OBResidue::GetNum(void) const
1258     {
1259     return _resnum;
1260     }
1261    
1262     unsigned int OBResidue::GetNumAtoms(void) const
1263     {
1264     return (unsigned int)_atoms.size();
1265     }
1266    
1267     char OBResidue::GetChain(void) const
1268     {
1269     return _chain;
1270     }
1271    
1272     unsigned int OBResidue::GetChainNum(void) const
1273     {
1274     if (isdigit(_chain))
1275     return (_chain - '0');
1276     else
1277     return (_chain - 'A' + 1);
1278     }
1279    
1280     unsigned int OBResidue::GetIdx(void) const
1281     {
1282     return(_idx);
1283     }
1284    
1285     unsigned int OBResidue::GetResKey(void) const
1286     {
1287     return(_reskey);
1288     }
1289    
1290     string OBResidue::GetAtomID(OBAtom *atom) const
1291     {
1292     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1293     if (_atoms[i] == atom)
1294     return _atomid[i];
1295     return "";
1296     }
1297    
1298     unsigned int OBResidue::GetSerialNum(OBAtom *atom) const
1299     {
1300     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1301     if (_atoms[i] == atom)
1302     return _sernum[i];
1303     return 0;
1304     }
1305    
1306     bool OBResidue::IsHetAtom(OBAtom *atom) const
1307     {
1308     for ( unsigned int i = 0 ; i < _atoms.size() ; i++ )
1309     if (_atoms[i] == atom)
1310     return _hetatm[i];
1311     return false;
1312     }
1313    
1314     ///////////////////////////////////////////////////////////////////////////////
1315     // OBResidue: Iteration Utilities
1316     ///////////////////////////////////////////////////////////////////////////////
1317    
1318     OBAtom *OBResidue::BeginAtom(vector<OBAtom*>::iterator &i)
1319     {
1320     i = _atoms.begin();
1321     return ((i == _atoms.end()) ? NULL : *i);
1322     }
1323    
1324     OBAtom *OBResidue::NextAtom(vector<OBAtom*>::iterator &i)
1325     {
1326     i++;
1327     return ((i == _atoms.end()) ? NULL : *i);
1328     }
1329    
1330     ///////////////////////////////////////////////////////////////////////////////
1331     // OBResidue: Information Functions
1332     ///////////////////////////////////////////////////////////////////////////////
1333    
1334     bool OBResidue::GetAminoAcidProperty(int property) const
1335     {
1336     switch(property)
1337     {
1338     case OBAminoAcidProperty::ACIDIC:
1339     return IS_ACIDIC(_aakey) != 0;
1340     case OBAminoAcidProperty::ACYCLIC:
1341     return IS_ACYCLIC(_aakey) != 0;
1342     case OBAminoAcidProperty::ALIPHATIC:
1343     return IS_ALIPHATIC(_aakey) != 0;
1344     case OBAminoAcidProperty::AROMATIC:
1345     return IS_AROMATIC(_aakey) != 0;
1346     case OBAminoAcidProperty::BASIC:
1347     return IS_BASIC(_aakey) != 0;
1348     case OBAminoAcidProperty::BURIED:
1349     return IS_BURIED(_aakey) != 0;
1350     case OBAminoAcidProperty::CHARGED:
1351     return IS_CHARGED(_aakey) != 0;
1352     case OBAminoAcidProperty::CYCLIC:
1353     return IS_CYCLIC(_aakey) != 0;
1354     case OBAminoAcidProperty::HYDROPHOBIC:
1355     return IS_HYDROPHOBIC(_aakey) != 0;
1356     case OBAminoAcidProperty::LARGE:
1357     return IS_LARGE(_aakey) != 0;
1358     case OBAminoAcidProperty::MEDIUM:
1359     return IS_MEDIUM(_aakey) != 0;
1360     case OBAminoAcidProperty::NEGATIVE:
1361     return IS_NEGATIVE(_aakey) != 0;
1362     case OBAminoAcidProperty::NEUTRAL:
1363     return IS_NEUTRAL(_aakey) != 0;
1364     case OBAminoAcidProperty::POLAR:
1365     return IS_POLAR(_aakey) != 0;
1366     case OBAminoAcidProperty::POSITIVE:
1367     return IS_POSITIVE(_aakey) != 0;
1368     case OBAminoAcidProperty::SMALL:
1369     return IS_SMALL(_aakey) != 0;
1370     case OBAminoAcidProperty::SURFACE:
1371     return IS_SURFACE(_aakey) != 0;
1372     default:
1373     return false;
1374     }
1375     }
1376    
1377     bool OBResidue::GetAtomProperty(OBAtom *atom, int property) const
1378     {
1379     if (atom != NULL)
1380     {
1381     unsigned int atomid = GetAtomIDNumber(GetAtomID(atom).c_str());
1382    
1383     switch(property)
1384     {
1385     case OBResidueAtomProperty::ALPHA_CARBON:
1386     return (atomid == 1);
1387    
1388     case OBResidueAtomProperty::AMINO_BACKBONE:
1389     return (atomid <= 3);
1390    
1391     case OBResidueAtomProperty::BACKBONE:
1392     return (atomid <= 18);
1393    
1394     case OBResidueAtomProperty::CYSTEINE_SULPHUR:
1395     return (atomid == 20);
1396    
1397     case OBResidueAtomProperty::LIGAND:
1398     return IsHetAtom(atom) &&
1399     !GetResidueProperty(OBResidueProperty::SOLVENT);
1400    
1401     case OBResidueAtomProperty::NUCLEIC_BACKBONE:
1402     return ((atomid >= 7) && (atomid <= 18));
1403    
1404     case OBResidueAtomProperty::SHAPELY_BACKBONE:
1405     return (atomid <= 7);
1406    
1407     case OBResidueAtomProperty::SHAPELY_SPECIAL:
1408     return (atomid == 19);
1409    
1410     case OBResidueAtomProperty::SIDECHAIN:
1411     return GetResidueProperty(OBResidueProperty::AMINO_NUCLEO) &&
1412     (atomid > 18);
1413    
1414     case OBResidueAtomProperty::SUGAR_PHOSPHATE:
1415     return (atomid == 7);
1416     }
1417     }
1418    
1419     return false;
1420     }
1421    
1422     bool OBResidue::GetResidueProperty(int property) const
1423     {
1424     switch(property)
1425     {
1426     case OBResidueProperty::AMINO:
1427     return (_reskey <= OBResidueIndex::HYP);
1428    
1429     case OBResidueProperty::AMINO_NUCLEO:
1430     return (_reskey <= OBResidueIndex::PSU);
1431    
1432     case OBResidueProperty::COENZYME:
1433     return (_reskey >= OBResidueIndex::NAD) &&
1434     (_reskey <= OBResidueIndex::NDP);
1435    
1436     case OBResidueProperty::ION:
1437     return (_reskey == OBResidueIndex::SO4) ||
1438     (_reskey == OBResidueIndex::PO4);
1439    
1440     case OBResidueProperty::NUCLEO:
1441     return (_reskey >= OBResidueIndex::A) &&
1442     (_reskey <= OBResidueIndex::PSU);
1443    
1444     case OBResidueProperty::PROTEIN:
1445     return (_reskey <= OBResidueIndex::HYP) ||
1446     ((_reskey >= OBResidueIndex::UNK) &&
1447     (_reskey <= OBResidueIndex::FOR));
1448    
1449     case OBResidueProperty::PURINE:
1450     return (_reskey == OBResidueIndex::A) ||
1451     (_reskey == OBResidueIndex::G);
1452    
1453     case OBResidueProperty::PYRIMIDINE:
1454     return (_reskey == OBResidueIndex::C) ||
1455     (_reskey == OBResidueIndex::T);
1456    
1457     case OBResidueProperty::SOLVENT:
1458     return (_reskey >= OBResidueIndex::HOH) &&
1459     (_reskey <= OBResidueIndex::PO4);
1460    
1461     case OBResidueProperty::WATER:
1462     return (_reskey == OBResidueIndex::HOH) ||
1463     (_reskey == OBResidueIndex::DOD);
1464    
1465     default:
1466     return false;
1467     }
1468     }
1469    
1470     bool OBResidue::IsResidueType(int restype) const
1471     {
1472     return ((int)_reskey == restype);
1473     }
1474    
1475     // OBGenericData methods
1476     bool OBResidue::HasData(string &s)
1477     //returns true if the generic attribute/value pair exists
1478     {
1479     if (_vdata.empty())
1480     return(false);
1481    
1482     vector<OBGenericData*>::iterator i;
1483    
1484     for (i = _vdata.begin();i != _vdata.end();i++)
1485     if ((*i)->GetAttribute() == s)
1486     return(true);
1487    
1488     return(false);
1489     }
1490    
1491     bool OBResidue::HasData(const char *s)
1492     //returns true if the generic attribute/value pair exists
1493     {
1494     if (_vdata.empty())
1495     return(false);
1496    
1497     vector<OBGenericData*>::iterator i;
1498    
1499     for (i = _vdata.begin();i != _vdata.end();i++)
1500     if ((*i)->GetAttribute() == s)
1501     return(true);
1502    
1503     return(false);
1504     }
1505    
1506     bool OBResidue::HasData(unsigned int dt)
1507     //returns true if the generic attribute/value pair exists
1508     {
1509     if (_vdata.empty())
1510     return(false);
1511    
1512     vector<OBGenericData*>::iterator i;
1513    
1514     for (i = _vdata.begin();i != _vdata.end();i++)
1515     if ((*i)->GetDataType() == dt)
1516     return(true);
1517    
1518     return(false);
1519     }
1520    
1521     OBGenericData *OBResidue::GetData(string &s)
1522     //returns the value given an attribute
1523     {
1524     vector<OBGenericData*>::iterator i;
1525    
1526     for (i = _vdata.begin();i != _vdata.end();i++)
1527     if ((*i)->GetAttribute() == s)
1528     return(*i);
1529    
1530     return(NULL);
1531     }
1532    
1533     OBGenericData *OBResidue::GetData(const char *s)
1534     //returns the value given an attribute
1535     {
1536     vector<OBGenericData*>::iterator i;
1537    
1538     for (i = _vdata.begin();i != _vdata.end();i++)
1539     if ((*i)->GetAttribute() == s)
1540     return(*i);
1541    
1542     return(NULL);
1543     }
1544    
1545     OBGenericData *OBResidue::GetData(unsigned int dt)
1546     {
1547     vector<OBGenericData*>::iterator i;
1548     for (i = _vdata.begin();i != _vdata.end();i++)
1549     if ((*i)->GetDataType() == dt)
1550     return(*i);
1551     return(NULL);
1552     }
1553    
1554     void OBResidue::DeleteData(unsigned int dt)
1555     {
1556     vector<OBGenericData*> vdata;
1557     vector<OBGenericData*>::iterator i;
1558     for (i = _vdata.begin();i != _vdata.end();i++)
1559     if ((*i)->GetDataType() == dt)
1560     delete *i;
1561     else
1562     vdata.push_back(*i);
1563     _vdata = vdata;
1564     }
1565    
1566     void OBResidue::DeleteData(vector<OBGenericData*> &vg)
1567     {
1568     vector<OBGenericData*> vdata;
1569     vector<OBGenericData*>::iterator i,j;
1570    
1571     bool del;
1572     for (i = _vdata.begin();i != _vdata.end();i++)
1573     {
1574     del = false;
1575     for (j = vg.begin();j != vg.end();j++)
1576     if (*i == *j)
1577     {
1578     del = true;
1579     break;
1580     }
1581     if (del)
1582     delete *i;
1583     else
1584     vdata.push_back(*i);
1585     }
1586     _vdata = vdata;
1587     }
1588    
1589     void OBResidue::DeleteData(OBGenericData *gd)
1590     {
1591     vector<OBGenericData*>::iterator i;
1592     for (i = _vdata.begin();i != _vdata.end();i++)
1593     if (*i == gd)
1594     {
1595     delete *i;
1596     _vdata.erase(i);
1597     }
1598    
1599     }
1600    
1601     } // end namespace OpenBabel
1602    
1603     //! \file residue.cpp
1604     //! \brief Handle macromolecule residues.