source: branches/stable/SL/HELIX/BI_helix.cxx

Last change on this file was 18463, checked in by westram, 4 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : BI_helix.cxx                                      //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "BI_helix.hxx"
12
13#include <arbdbt.h>
14
15#include <cctype>
16
17#define LEFT_HELIX "{[<("
18#define RIGHT_HELIX "}]>)"
19#define LEFT_NONS "#*abcdefghij"
20#define RIGHT_NONS "#*ABCDEFGHIJ"
21
22char *BI_helix::helix_error = NULp;
23
24struct helix_stack {
25    struct helix_stack *next;
26    long    pos;
27    BI_PAIR_TYPE type;
28    char    c;
29};
30
31void BI_helix::_init() {
32    int i;
33    for (i=0; i<HELIX_MAX; i++) pairs[i]     = NULp;
34    for (i=0; i<HELIX_MAX; i++) char_bind[i] = NULp;
35
36    entries = NULp;
37    Size    = 0;
38
39    pairs[HELIX_NONE]=strdup("");
40    char_bind[HELIX_NONE] = strdup(" ");
41
42    pairs[HELIX_STRONG_PAIR]=strdup("CG AT AU");
43    char_bind[HELIX_STRONG_PAIR] = strdup("~");
44
45    pairs[HELIX_PAIR]=strdup("GT GU");
46    char_bind[HELIX_PAIR] = strdup("-");
47
48    pairs[HELIX_WEAK_PAIR]=strdup("GA");
49    char_bind[HELIX_WEAK_PAIR] = strdup("=");
50
51    pairs[HELIX_NO_PAIR]=strdup("AA AC CC CT CU GG TU");
52    char_bind[HELIX_NO_PAIR] = strdup("#");
53
54    pairs[HELIX_USER0]=strdup(".A .C .G .T .U");
55    char_bind[HELIX_USER0] = strdup("*");
56
57    pairs[HELIX_USER1]=strdup("-A -C -G -T -U");
58    char_bind[HELIX_USER1] = strdup("#");
59
60    pairs[HELIX_USER2]=strdup("UU TT");
61    char_bind[HELIX_USER2] = strdup("+");
62
63    pairs[HELIX_USER3]=strdup("");
64    char_bind[HELIX_USER3] = strdup("");
65
66    pairs[HELIX_DEFAULT]=strdup("");
67    char_bind[HELIX_DEFAULT] = strdup("");
68
69    for (i=HELIX_NON_STANDARD0; i<=HELIX_NON_STANDARD9; i++) {
70        pairs[i] = strdup("");
71        char_bind[i] = strdup("");
72    }
73
74    pairs[HELIX_NO_MATCH]=strdup("");
75    char_bind[HELIX_NO_MATCH] = strdup("|");
76}
77
78BI_helix::BI_helix() {
79    _init();
80}
81
82BI_helix::~BI_helix() {
83    unsigned i;
84    for (i=0; i<HELIX_MAX; i++) free(pairs[i]);
85    for (i=0; i<HELIX_MAX; i++) free(char_bind[i]);
86
87    if (entries) {
88        for (i = 0; i<Size; ++i) {
89            if (entries[i].allocated) {
90                free(entries[i].helix_nr);
91            }
92        }
93        free(entries);
94    }
95}
96
97static void BI_helix_check_error(const char *key, long val, void *) {
98    struct helix_stack *stack = (struct helix_stack *)val;
99    if (!BI_helix::get_error() && stack) { // don't overwrite existing error
100        BI_helix::set_error(GBS_global_string("Too many '%c' in Helix '%s' pos %li", stack->c, key, stack->pos));
101    }
102}
103
104
105static long BI_helix_free_hash(const char *, long val, void *) {
106    struct helix_stack *stack = (struct helix_stack *)val;
107    struct helix_stack *next;
108    for (; stack; stack = next) {
109        next = stack->next;
110        delete stack;
111    }
112    return 0;
113}
114
115const char *BI_helix::initFromData(const char *helix_nr_in, const char *helix_in, size_t sizei) {
116    /* helix_nr string of helix identifiers
117     * helix    helix
118     * size     alignment len
119     */
120    clear_error();
121
122    GB_HASH *hash = GBS_create_hash(256, GB_IGNORE_CASE);
123    size_t   pos;
124    char     c;
125    char     ident[256];
126    char    *sident;
127   
128    helix_stack *laststack = NULp;
129    helix_stack *stack;
130
131    Size = sizei;
132
133    char *helix = NULp;
134    {
135        size_t len          = strlen(helix_in);
136        if (len > Size) len = Size;
137
138        char *h = ARB_alloc<char>(Size+1);
139        h[Size] = 0;
140
141        if (len<Size) memset(h+len, '.', Size-len);
142        memcpy(h, helix_in, len);
143        helix = h;
144    }
145
146    char *helix_nr = NULp;
147    if (helix_nr_in) {
148        size_t len          = strlen(helix_nr_in);
149        if (len > Size) len = (int)Size;
150
151        char *h = ARB_alloc<char>(Size+1);
152        h[Size] = 0;
153
154        if (len<Size) memset(h+len, '.', (int)(Size-len));
155        memcpy(h, helix_nr_in, len);
156        helix_nr = h;
157    }
158
159    strcpy(ident, "0");
160    long pos_scanned_till = -1;
161
162    ARB_calloc(entries, Size);
163    sident  = NULp;
164
165    for (pos = 0; pos < Size; pos ++) {
166        if (helix_nr) {
167            if (long(pos)>pos_scanned_till && isalnum(helix_nr[pos])) {
168                for (int j=0; (pos+j)<Size; j++) {
169                    char hn = helix_nr[pos+j];
170                    if (isalnum(hn)) {
171                        ident[j] = hn;
172                    }
173                    else {
174                        ident[j]         = 0;
175                        pos_scanned_till = pos+j;
176                        break;
177                    }
178                }
179            }
180        }
181        c = helix[pos];
182        if (strchr(LEFT_HELIX, c) || strchr(LEFT_NONS, c)) { // push
183            laststack = (struct helix_stack *)GBS_read_hash(hash, ident);
184            stack = new helix_stack;
185            stack->next = laststack;
186            stack->pos = pos;
187            stack->c = c;
188            GBS_write_hash(hash, ident, (long)stack);
189        }
190        else if (strchr(RIGHT_HELIX, c) || strchr(RIGHT_NONS, c)) { // pop
191            stack = (struct helix_stack *)GBS_read_hash(hash, ident);
192            if (!stack) {
193                bi_assert(!helix_error); // already have an error
194                helix_error = GBS_global_string_copy("Too many '%c' in Helix '%s' pos %zu", c, ident, pos);
195                goto helix_end;
196            }
197            if (strchr(RIGHT_HELIX, c)) {
198                entries[pos].pair_type = HELIX_PAIR;
199                entries[stack->pos].pair_type = HELIX_PAIR;
200            }
201            else {
202                c = tolower(c);
203                if (stack->c != c) {
204                    bi_assert(!helix_error); // already have an error
205                    helix_error = GBS_global_string_copy("Character '%c' pos %li doesn't match character '%c' pos %zu in Helix '%s'",
206                                                         stack->c, stack->pos, c, pos, ident);
207                    goto helix_end;
208                }
209                if (isalpha(c)) {
210                    entries[pos].pair_type = (BI_PAIR_TYPE)(HELIX_NON_STANDARD0+c-'a');
211                    entries[stack->pos].pair_type = (BI_PAIR_TYPE)(HELIX_NON_STANDARD0+c-'a');
212                }
213                else {
214                    entries[pos].pair_type = HELIX_NO_PAIR;
215                    entries[stack->pos].pair_type = HELIX_NO_PAIR;
216                }
217            }
218            entries[pos].pair_pos = stack->pos;
219            entries[stack->pos].pair_pos = pos;
220            GBS_write_hash(hash, ident, (long)stack->next);
221
222            if (!sident || strcmp(sident+1, ident) != 0) {
223                ARB_alloc(sident, strlen(ident)+2);
224                sprintf(sident, "-%s", ident);
225
226                entries[stack->pos].allocated = true;
227            }
228            entries[pos].helix_nr        = sident+1;
229            entries[stack->pos].helix_nr = sident;
230            bi_assert((long)pos != stack->pos);
231
232            delete stack;
233        }
234    }
235
236    GBS_hash_do_const_loop(hash, BI_helix_check_error, NULp);
237
238 helix_end :
239    GBS_hash_do_loop(hash, BI_helix_free_hash, NULp);
240    GBS_free_hash(hash);
241
242    free(helix_nr);
243    free(helix);
244
245    return get_error();
246}
247
248
249const char *BI_helix::init(GBDATA *gb_helix_nr, GBDATA *gb_helix, size_t sizei) {
250    clear_error();
251
252    if (!gb_helix) set_error("Can't find SAI:HELIX");
253    else if (!gb_helix_nr) set_error("Can't find SAI:HELIX_NR");
254    else {
255        GB_transaction ta(gb_helix);
256        initFromData(GB_read_char_pntr(gb_helix_nr), GB_read_char_pntr(gb_helix), sizei); // @@@ NOT_ALL_SAI_HAVE_DATA
257    }
258
259    return get_error();
260}
261
262const char *BI_helix::init(GBDATA *gb_main, const char *alignment_name, const char *helix_nr_name, const char *helix_name) {
263    GB_transaction ta(gb_main);
264    clear_error();
265
266    GBDATA *gb_sai_data = GBT_get_SAI_data(gb_main);
267    long    size2       = GBT_get_alignment_len(gb_main, alignment_name);
268
269    if (size2<=0) {
270        set_error(size2<0 ? GB_await_error() : "no data in alignment");
271    }
272    else {
273        GBDATA *gb_helix_nr_con = GBT_find_SAI_rel_SAI_data(gb_sai_data, helix_nr_name);
274        GBDATA *gb_helix_con    = GBT_find_SAI_rel_SAI_data(gb_sai_data, helix_name);
275        GBDATA *gb_helix        = NULp;
276        GBDATA *gb_helix_nr     = NULp;
277
278        if (gb_helix_nr_con)    gb_helix_nr = GBT_find_sequence(gb_helix_nr_con, alignment_name);
279        if (gb_helix_con)       gb_helix    = GBT_find_sequence(gb_helix_con, alignment_name);
280
281        init(gb_helix_nr, gb_helix, size2);
282    }
283
284    return get_error();
285}
286
287const char *BI_helix::init(GBDATA *gb_main, const char *alignment_name) {
288    GB_transaction ta(gb_main);
289
290    char *helix    = GBT_get_default_helix(gb_main);
291    char *helix_nr = GBT_get_default_helix_nr(gb_main);
292
293    const char *err = init(gb_main, alignment_name, helix_nr, helix);
294
295    free(helix);
296    free(helix_nr);
297
298    return err;
299}
300
301const char *BI_helix::init(GBDATA *gb_main) {
302    GB_transaction ta(gb_main);
303
304    char       *alignment_name = GBT_get_default_alignment(gb_main);
305    const char *err            = init(gb_main, alignment_name);
306
307    free(alignment_name);
308    return err;
309}
310
311bool BI_helix::is_pairtype(char left, char right, BI_PAIR_TYPE pair_type) {
312    int   len = strlen(pairs[pair_type])-1;
313    char *pai = pairs[pair_type];
314
315    for (int i=0; i<len; i+=3) {
316        if ((pai[i] == left && pai[i+1] == right) ||
317            (pai[i] == right && pai[i+1] == left)) return true;
318    }
319    return false;
320}
321
322int BI_helix::check_pair(char left, char right, BI_PAIR_TYPE pair_type) {
323    // return value:
324    // 2  = helix
325    // 1  = weak helix
326    // 0  = no helix
327    // -1 = nothing
328
329    left  = toupper(left);
330    right = toupper(right);
331    switch (pair_type) {
332        case HELIX_PAIR:
333            if (is_pairtype(left, right, HELIX_STRONG_PAIR) ||
334                is_pairtype(left, right, HELIX_PAIR)) return 2;
335            if (is_pairtype(left, right, HELIX_WEAK_PAIR)) return 1;
336            return 0;
337
338        case HELIX_NO_PAIR:
339            if (is_pairtype(left, right, HELIX_STRONG_PAIR) ||
340                is_pairtype(left, right, HELIX_PAIR)) return 0;
341            return 1;
342
343        default:
344            return is_pairtype(left, right, pair_type) ? 1 : 0;
345    }
346}
347
348long BI_helix::first_pair_position() const {
349    return entries[0].pair_type == HELIX_NONE ? next_pair_position(0) : 0;
350}
351
352long BI_helix::next_pair_position(size_t pos) const {
353    if (entries[pos].next_pair_pos == 0) {
354        size_t p;
355        long   next_pos = -1;
356        for (p = pos+1; p<Size && next_pos == -1; ++p) {
357            if (entries[p].pair_type != HELIX_NONE) {
358                next_pos = p;
359            }
360            else if (entries[p].next_pair_pos != 0) {
361                next_pos = entries[p].next_pair_pos;
362            }
363        }
364
365        size_t q = p<Size ? p-2 : Size-1;
366
367        for (p = pos; p <= q; ++p) {
368            bi_assert(entries[p].next_pair_pos == 0);
369            entries[p].next_pair_pos = next_pos;
370        }
371    }
372    return entries[pos].next_pair_pos;
373}
374
375long BI_helix::first_position(const char *helix_Nr) const {
376    long pos;
377    for (pos = first_pair_position(); pos != -1; pos = next_pair_position(pos)) {
378        if (strcmp(helix_Nr, entries[pos].helix_nr) == 0) break;
379    }
380    return pos;
381}
382
383long BI_helix::last_position(const char *helix_Nr) const {
384    long pos = first_position(helix_Nr);
385    if (pos != -1) {
386        long next_pos = next_pair_position(pos);
387        while (next_pos != -1 && strcmp(helix_Nr, entries[next_pos].helix_nr) == 0) {
388            pos      = next_pos;
389            next_pos = next_pair_position(next_pos);
390        }
391    }
392    return pos;
393}
394
Note: See TracBrowser for help on using the repository browser.