source: tags/arb_5.2/AWT/AWT_iupac.cxx

Last change on this file was 5773, checked in by westram, 15 years ago
  • If not a valid IUPAC, AWT_decode_iupac() now returns "" (previously " ") for easier testing.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.2 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <ctype.h>
4
5#include <arb_assert.h>
6#define awt_assert(bed) arb_assert(bed)
7
8#include "awt_iupac.hxx"
9
10#define IUPAC_EMPTY "" // changed from " " to "" (2009-03-19 -- ralf)
11#define ILL_CODE char(26)
12
13AWT_IUPAC_descriptor AWT_iupac_code[26][2]= {
14    {{ "A",     1 }, { "A",     1 }},
15    {{ "CGT",   3 }, { "CGU",   3 }},
16    {{ "C",     1 }, { "C",     1 }},
17    {{ "AGT",   3 }, { "AGU",   3 }},
18    {{ 0,       0 }, { 0,       0 }}, // E
19    {{ 0,       0 }, { 0,       0 }}, // F
20    {{ "G",     1 }, { "G",     1 }},
21    {{ "ACT",   3 }, { "ACU",   3 }},
22    {{ 0,       0 }, { 0,       0 }}, // I
23    {{ 0,       0 }, { 0,       0 }}, // J
24    {{ "GT",    2 }, { "GU",    2 }},
25    {{ 0,       0 }, { 0,       0 }}, // L
26    {{ "AC",    2 }, { "AC",    2 }},
27    {{ "ACGT",  1 }, { "ACGU",  1 }}, // N
28    {{ 0,       0 }, { 0,       0 }}, // O
29    {{ 0,       0 }, { 0,       0 }}, // P
30    {{ 0,       0 }, { 0,       0 }}, // Q
31    {{ "AG",    2 }, { "AG",    2 }},
32    {{ "CG",    2 }, { "CG",    2 }},
33    {{ "T",     1 }, { "U",     1 }}, // T
34    {{ "T",     1 }, { "U",     1 }}, // U
35    {{ "ACG",   3 }, { "ACG",   3 }},
36    {{ "AT",    2 }, { "AU",    2 }},
37    {{ 0,       0 }, { 0,       0 }}, // X
38    {{ "CT",    2 }, { "CU",    2 }},
39    {{ 0,       0 }, { 0,       0 }}  // Z
40
41    // (In each single string the nucs have to be sorted alphabetically)
42};
43
44const int AWT_iupac_group[26] =  { // this is for amino_acids
45    1, // A
46    2, // B
47    0, // C
48    2, // D
49    2, // E
50    5, // F
51    1, // G
52    3, // H
53    4, // I
54    0, // J
55    3, // K
56    4, // L
57    4, // M
58    2, // N
59    0, // O
60    1, // P
61    2, // Q
62    3, // R
63    1, // S
64    1, // T
65    0, // U
66    4, // V
67    5, // W
68    0, // X
69    5, // Y
70    2, // Z
71};
72
73static char IUPAC_add[26][26]; // uses T
74static int IUPAC_add_initialized = 0;
75
76static void initialize_IUPAC_add()
77{
78    int c1, c2;
79
80    for (c1=0; c1<26; c1++) {
81        const char *decoded1 = AWT_iupac_code[c1][0].iupac;
82
83        if (!decoded1) {
84            for (c2=0; c2<=c1; c2++) {
85                IUPAC_add[c1][c2] = ILL_CODE;
86                IUPAC_add[c2][c1] = ILL_CODE;
87            }
88        }
89        else {
90            IUPAC_add[c1][c1] = char(c1);       // add char to same char
91
92            for (c2=0; c2<c1; c2++) {
93                if (strchr(decoded1, 'A'+c2)!=0) {      // char is already contained in this IUPAC
94                    IUPAC_add[c1][c2] = char(c1);
95                }
96                else {
97                    const char *decoded2 = AWT_iupac_code[c2][0].iupac;
98
99                    if (!decoded2) { // char is illegal
100                        IUPAC_add[c1][c2] = ILL_CODE;
101                    }
102                    else {
103#define MAX_MIXED 5
104                        char mixed[MAX_MIXED];
105                        char *mp = mixed;
106                        const char *d1 = decoded1;
107                        const char *d2 = decoded2;
108
109                        while (1) {
110                            char z1 = *d1;
111                            char z2 = *d2;
112
113                            if (!z1 && !z2) break;
114
115                            if (z1==z2) {
116                                *mp++ = z1;
117                                d1++;
118                                d2++;
119                            }
120                            else if (!z2 || (z1 && z1<z2)) {
121                                *mp++ = z1;
122                                d1++;
123                            }
124                            else {
125                                awt_assert(!z1 || (z2 && z2<z1));
126                                *mp++ = z2;
127                                d2++;
128                            }
129                        }
130
131                        awt_assert((mp-mixed)<MAX_MIXED);
132                        *mp++ = 0;
133
134#if !defined(NDEBUG) && 0
135                        printf("Mix '%s' + '%s' = '%s'\n", decoded1, decoded2, mixed);
136#endif
137
138                        int c3;
139
140                        for (c3=0; c3<26; c3++) {
141                            if (AWT_iupac_code[c3][0].iupac && strcmp(mixed, AWT_iupac_code[c3][0].iupac)==0) {
142                                IUPAC_add[c1][c2] = char(c3);
143                                break;
144                            }
145                        }
146
147                        if (c3>=26) {
148                            IUPAC_add[c1][c2] = 0;
149                        }
150                    }
151                }
152
153                if (IUPAC_add[c1][c2]==('U'-'A')) {
154                    IUPAC_add[c1][c2] = 'T'-'A';
155                }
156
157                IUPAC_add[c2][c1] = IUPAC_add[c1][c2];
158            }
159        }
160
161    }
162}
163
164char AWT_encode_iupac(const char bases[], GB_alignment_type ali)
165{
166    if (!IUPAC_add_initialized) {
167        initialize_IUPAC_add();
168        IUPAC_add_initialized = 1;
169    }
170
171    if (ali==GB_AT_AA) {
172        return '?';
173    }
174
175    int i = 0;
176    unsigned char c1;
177
178    while (1) {
179        c1 = bases[i++];
180        if (!c1) return '-';
181        if (isalpha(c1)) break;
182    }
183
184    c1 = toupper(c1)-'A';
185    unsigned char c = IUPAC_add[c1][c1];
186
187    while (c!=ILL_CODE && bases[i]) {
188        if (isalpha(bases[i])) {
189            int c2 = toupper(bases[i])-'A';
190            c = IUPAC_add[c][c2];
191        }
192        i++;
193    }
194
195    if (c==ILL_CODE) {
196        return '-';
197    }
198
199    c += 'A';
200    if (c=='T' && ali==GB_AT_RNA) c = 'U';
201    return c;
202}
203
204char AWT_iupac_add(char c1, char c2, GB_alignment_type ali) {
205    static char buffer[3];
206    buffer[0] = c1;
207    buffer[1] = c2;
208    buffer[2] = 0;
209    return AWT_encode_iupac(buffer, ali);
210}
211
212const char* AWT_decode_iupac(char iupac, GB_alignment_type ali, int decode_amino_iupac_groups)
213{
214    if (!isalpha(iupac)) {
215        return IUPAC_EMPTY;
216    }
217
218    if (ali==GB_AT_AA) {
219        if (decode_amino_iupac_groups) {
220            int group = AWT_iupac_group[toupper(iupac)-'A'];
221
222            switch (group) {
223                case 1: return "AGPST";
224                case 2: return "BDENQZ";
225                case 3: return "HKR";
226                case 4: return "ILMV";
227                case 5: return "FWY";
228            }
229        }
230        return "?";
231    }
232
233    const char *decoded = AWT_iupac_code[toupper(iupac)-'A'][ali==GB_AT_RNA ? 1 : 0].iupac;
234
235    return decoded ? decoded : IUPAC_EMPTY;
236}
Note: See TracBrowser for help on using the repository browser.