source: tags/arb_5.1/EDIT4/ED4_mini_classes.cxx

Last change on this file was 5929, checked in by westram, 15 years ago
  • added AW_awar::read_char_pntr()
  • stuffed several memory leaks
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.8 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <ctype.h>
4
5#include <arbdb.h>
6#include <aw_root.hxx>
7#include <aw_window.hxx>
8
9#include <awt_iupac.hxx>
10
11#include "ed4_class.hxx"
12#include "ed4_edit_string.hxx"
13#include "ed4_awars.hxx"
14#include "ed4_tools.hxx"
15
16
17// --------------------------------------------------------------------------------
18//              ED4_folding_line::
19// --------------------------------------------------------------------------------
20
21ED4_folding_line::ED4_folding_line()
22{
23    memset((char *)this,0,sizeof(*this));
24}
25ED4_folding_line::~ED4_folding_line()
26{
27}
28
29// --------------------------------------------------------------------------------
30//              ED4_bases_table::
31// --------------------------------------------------------------------------------
32
33#ifdef DEBUG
34//# define COUNT_BASES_TABLE_SIZE
35#endif
36
37#ifdef COUNT_BASES_TABLE_SIZE
38static long bases_table_size = 0L;
39#endif
40
41void ED4_bases_table::init(int length)
42{
43    if (length) {
44        if (no_of_bases.shortTable) {
45            delete no_of_bases.shortTable;
46            no_of_bases.shortTable = 0;
47#ifdef COUNT_BASES_TABLE_SIZE
48            bases_table_size -= (no_of_entries+1)*table_entry_size;
49#endif
50        }
51
52        no_of_entries = length;
53        int new_size = (no_of_entries+1)*table_entry_size;
54        no_of_bases.shortTable = (unsigned char*)new char[new_size];
55        memset(no_of_bases.shortTable, 0, new_size);
56#ifdef COUNT_BASES_TABLE_SIZE
57        bases_table_size += new_size;
58        printf("bases_table_size = %li\n", bases_table_size);
59#endif
60    }
61}
62
63void ED4_bases_table::expand_table_entry_size() { // converts short table into long table
64    e4_assert(table_entry_size==SHORT_TABLE_ELEM_SIZE);
65
66    int *new_table = new int[no_of_entries+1];
67    int i;
68
69    for (i=0; i<=no_of_entries; i++) {
70        new_table[i] = no_of_bases.shortTable[i];
71    }
72    delete [] no_of_bases.shortTable;
73
74#ifdef COUNT_BASES_TABLE_SIZE
75    bases_table_size += (no_of_entries+1)*(LONG_TABLE_ELEM_SIZE-SHORT_TABLE_ELEM_SIZE);
76    printf("bases_table_size = %li\n", bases_table_size);
77#endif
78
79    no_of_bases.longTable = new_table;
80    table_entry_size = LONG_TABLE_ELEM_SIZE;
81}
82
83void ED4_bases_table::add(const ED4_bases_table& other, int start, int end)
84{
85    e4_assert(no_of_entries==other.no_of_entries);
86    e4_assert(start>=0);
87    e4_assert(end<no_of_entries);
88    e4_assert(start<=end);
89
90    int i;
91    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
92        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
93            for (i=start; i<=end; i++) {
94                set_elem_short(i, get_elem_short(i)+other.get_elem_short(i));
95            }
96        }
97        else {
98            for (i=start; i<=end; i++) {
99                set_elem_short(i, get_elem_short(i)+other.get_elem_long(i));
100            }
101        }
102    }
103    else {
104        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
105            for (i=start; i<=end; i++) {
106                set_elem_long(i, get_elem_long(i)+other.get_elem_short(i));
107            }
108        }
109        else {
110            for (i=start; i<=end; i++) {
111                set_elem_long(i, get_elem_long(i)+other.get_elem_long(i));
112            }
113        }
114    }
115}
116void ED4_bases_table::sub(const ED4_bases_table& other, int start, int end)
117{
118    e4_assert(no_of_entries==other.no_of_entries);
119    e4_assert(start>=0);
120    e4_assert(end<no_of_entries);
121    e4_assert(start<=end);
122
123    int i;
124    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
125        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
126            for (i=start; i<=end; i++) {
127                set_elem_short(i, get_elem_short(i)-other.get_elem_short(i));
128            }
129        }
130        else {
131            for (i=start; i<=end; i++) {
132                set_elem_short(i, get_elem_short(i)-other.get_elem_long(i));
133            }
134        }
135    }
136    else {
137        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
138            for (i=start; i<=end; i++) {
139                set_elem_long(i, get_elem_long(i)-other.get_elem_short(i));
140            }
141        }
142        else {
143            for (i=start; i<=end; i++) {
144                set_elem_long(i, get_elem_long(i)-other.get_elem_long(i));
145            }
146        }
147    }
148}
149void ED4_bases_table::sub_and_add(const ED4_bases_table& Sub, const ED4_bases_table& Add, int start, int end)
150{
151    e4_assert(no_of_entries==Sub.no_of_entries);
152    e4_assert(no_of_entries==Add.no_of_entries);
153    e4_assert(start>=0);
154    e4_assert(end<no_of_entries);
155    e4_assert(start<=end);
156
157    int i;
158    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
159        if (Sub.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
160            if (Add.table_entry_size==SHORT_TABLE_ELEM_SIZE)  {
161                for (i=start; i<=end; i++) {
162                    set_elem_short(i, get_elem_short(i)-Sub.get_elem_short(i)+Add.get_elem_short(i));
163                }
164            }
165            else {
166                for (i=start; i<=end; i++) {
167                    set_elem_short(i, get_elem_short(i)-Sub.get_elem_short(i)+Add.get_elem_long(i));
168                }
169            }
170        }
171        else {
172            if (Add.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
173                for (i=start; i<=end; i++) {
174                    set_elem_short(i, get_elem_short(i)-Sub.get_elem_long(i)+Add.get_elem_short(i));
175                }
176            }
177            else {
178                for (i=start; i<=end; i++) {
179                    set_elem_short(i, get_elem_short(i)-Sub.get_elem_long(i)+Add.get_elem_long(i));
180                }
181            }
182        }
183    }
184    else {
185        if (Sub.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
186            if (Add.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
187                for (i=start; i<=end; i++) {
188                    set_elem_long(i, get_elem_long(i)-Sub.get_elem_short(i)+Add.get_elem_short(i));
189                }
190            }
191            else {
192                for (i=start; i<=end; i++) {
193                    set_elem_long(i, get_elem_long(i)-Sub.get_elem_short(i)+Add.get_elem_long(i));
194                }
195            }
196        }
197        else {
198            if (Add.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
199                for (i=start; i<=end; i++) {
200                    set_elem_long(i, get_elem_long(i)-Sub.get_elem_long(i)+Add.get_elem_short(i));
201                }
202            }
203            else {
204                for (i=start; i<=end; i++) {
205                    set_elem_long(i, get_elem_long(i)-Sub.get_elem_long(i)+Add.get_elem_long(i));
206                }
207            }
208        }
209    }
210}
211
212int ED4_bases_table::firstDifference(const ED4_bases_table& other, int start, int end, int *firstDifferentPos) const
213{
214    int i;
215    int result = 0;
216
217    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
218        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
219            for (i=start; i<=end; i++) {
220                if (get_elem_short(i)!=other.get_elem_short(i)) {
221                    *firstDifferentPos = i;
222                    result = 1;
223                    break;
224                }
225            }
226        }
227        else {
228            for (i=start; i<=end; i++) {
229                if (get_elem_short(i)!=other.get_elem_long(i)) {
230                    *firstDifferentPos = i;
231                    result = 1;
232                    break;
233                }
234            }
235        }
236    }
237    else {
238        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
239            for (i=start; i<=end; i++) {
240                if (get_elem_long(i)!=other.get_elem_short(i)) {
241                    *firstDifferentPos = i;
242                    result = 1;
243                    break;
244                }
245            }
246        }
247        else {
248            for (i=start; i<=end; i++) {
249                if (get_elem_long(i)!=other.get_elem_long(i)) {
250                    *firstDifferentPos = i;
251                    result = 1;
252                    break;
253                }
254            }
255        }
256    }
257
258    return result;
259}
260int ED4_bases_table::lastDifference(const ED4_bases_table& other, int start, int end, int *lastDifferentPos) const
261{
262    int i;
263    int result = 0;
264
265    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
266        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
267            for (i=end; i>=start; i--) {
268                if (get_elem_short(i)!=other.get_elem_short(i)) {
269                    *lastDifferentPos = i;
270                    result = 1;
271                    break;
272                }
273            }
274        }
275        else {
276            for (i=end; i>=start; i--) {
277                if (get_elem_short(i)!=other.get_elem_long(i)) {
278                    *lastDifferentPos = i;
279                    result = 1;
280                    break;
281                }
282            }
283        }
284    }
285    else {
286        if (other.table_entry_size==SHORT_TABLE_ELEM_SIZE) {
287            for (i=end; i>=start; i--) {
288                if (get_elem_long(i)!=other.get_elem_short(i)) {
289                    *lastDifferentPos = i;
290                    result = 1;
291                    break;
292                }
293            }
294        }
295        else {
296            for (i=end; i>=start; i--) {
297                if (get_elem_long(i)!=other.get_elem_long(i)) {
298                    *lastDifferentPos = i;
299                    result = 1;
300                    break;
301                }
302            }
303        }
304    }
305
306    return result;
307}
308
309
310ED4_bases_table::ED4_bases_table(int maxseqlength)
311{
312    memset((char*)this,0,sizeof(*this));
313    table_entry_size = SHORT_TABLE_ELEM_SIZE;
314    if (maxseqlength) init(maxseqlength);
315}
316
317ED4_bases_table::~ED4_bases_table()
318{
319    delete [] no_of_bases.shortTable;
320#ifdef COUNT_BASES_TABLE_SIZE
321    bases_table_size -= (no_of_entries+1)*table_entry_size;
322    printf("bases_table_size = %li\n", bases_table_size);
323#endif
324}
325
326void ED4_bases_table::change_table_length(int new_length, int default_entry)
327{
328    if (new_length!=no_of_entries) {
329        int min_length = new_length<no_of_entries ? new_length : no_of_entries;
330        int growth = new_length-no_of_entries;
331
332        if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
333            unsigned char *new_table = new unsigned char[new_length+1];
334
335            e4_assert(default_entry>=0 && default_entry<256);
336
337            memcpy(new_table, no_of_bases.shortTable, min_length*sizeof(*new_table));
338            new_table[new_length] = no_of_bases.shortTable[no_of_entries];
339            if (growth>0) {
340                for (int e=no_of_entries; e<new_length; ++e) new_table[e] = default_entry;
341                //memset(new_table+no_of_entries, 0, growth*sizeof(*new_table));
342            }
343
344            delete [] no_of_bases.shortTable;
345            no_of_bases.shortTable = new_table;
346        }
347        else {
348            int *new_table = new int[new_length+1];
349
350            memcpy(new_table, no_of_bases.longTable, min_length*sizeof(*new_table));
351            new_table[new_length] = no_of_bases.longTable[no_of_entries];
352            if (growth>0) {
353                for (int e=no_of_entries; e<new_length; ++e) new_table[e] = default_entry;
354                //memset(new_table+no_of_entries, 0, growth*sizeof(*new_table));
355            }
356
357            delete [] no_of_bases.longTable;
358            no_of_bases.longTable = new_table;
359        }
360
361#ifdef COUNT_BASES_TABLE_SIZE
362        bases_table_size += growth*table_entry_size;
363        printf("bases_table_size = %li\n", bases_table_size);
364#endif
365        no_of_entries = new_length;
366    }
367}
368
369#if defined(ASSERTION_USED)
370
371int ED4_bases_table::empty() const
372{
373    int i;
374
375    if (table_entry_size==SHORT_TABLE_ELEM_SIZE) {
376        for (i=0; i<no_of_entries; i++) {
377            if (get_elem_short(i)) {
378                return 0;
379            }
380        }
381    }
382    else {
383        for (i=0; i<no_of_entries; i++) {
384            if (get_elem_long(i)) {
385                return 0;
386            }
387        }
388    }
389
390    return 1;
391}
392#endif // ASSERTION_USED
393
394/* --------------------------------------------------------------------------------
395   Build consensus
396   -------------------------------------------------------------------------------- */
397
398// we make static copies of the awars to avoid performance breakdown (BK_up_to_date is changed by callback ED4_consensus_definition_changed)
399
400static int BK_up_to_date = 0;
401static int BK_countgaps;
402static int BK_gapbound;
403static int BK_group;
404static int BK_considbound;
405static int BK_upper;
406static int BK_lower;
407
408void ED4_consensus_definition_changed(AW_root*, AW_CL,AW_CL) {
409    ED4_terminal *terminal = ED4_ROOT->root_group_man->get_first_terminal();
410
411    e4_assert(terminal);
412    while (terminal) {
413        if (terminal->parent->parent->flag.is_consensus) {
414            terminal->set_refresh();
415            terminal->parent->refresh_requested_by_child();
416        }
417        terminal = terminal->get_next_terminal();
418    }
419
420    BK_up_to_date = 0;
421    // ED4_ROOT->root_group_man->Show();
422    ED4_ROOT->refresh_all_windows(1);
423}
424
425static ED4_returncode toggle_consensus_display(void **show, void **, ED4_base *base) {
426    if (base->flag.is_consensus) {
427        ED4_manager *consensus_man = base->to_manager();
428        ED4_spacer_terminal *spacer = consensus_man->parent->get_defined_level(ED4_L_SPACER)->to_spacer_terminal();
429
430        if (show) {
431            consensus_man->make_children_visible();
432            spacer->extension.size[HEIGHT] = SPACERHEIGHT;
433        }
434        else {
435            consensus_man->hide_children();
436
437            ED4_group_manager *group_man = consensus_man->get_parent(ED4_L_GROUP)->to_group_manager();
438            spacer->extension.size[HEIGHT] = (group_man->dynamic_prop&ED4_P_IS_FOLDED) ? SPACERNOCONSENSUSHEIGHT : SPACERHEIGHT;
439        }
440    }
441
442    return ED4_R_OK;
443}
444
445void ED4_consensus_display_changed(AW_root *root, AW_CL, AW_CL) {
446    int show = root->awar(ED4_AWAR_CONSENSUS_SHOW)->read_int();
447    ED4_ROOT->root_group_man->route_down_hierarchy((void**)show, 0, toggle_consensus_display);
448    ED4_ROOT->refresh_all_windows(1);
449}
450
451char *ED4_char_table::build_consensus_string(int left_idx, int right_idx, char *fill_id) const
452// consensus is only built in intervall
453// Note : Always check that consensus behavior is identical to that used in CON_evaluatestatistic()
454{
455    int i;
456
457    if (!BK_up_to_date) {
458        BK_countgaps = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_COUNTGAPS)->read_int();
459        BK_gapbound = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_GAPBOUND)->read_int();
460        BK_group = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_GROUP)->read_int();
461        BK_considbound = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_CONSIDBOUND)->read_int();
462        BK_upper = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_UPPER)->read_int();
463        BK_lower = ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_LOWER)->read_int();
464        BK_up_to_date = 1;
465    }
466
467    if (!fill_id) {
468        long entr = size();
469
470        fill_id = new char[entr+1];
471        fill_id[entr] = 0;
472    }
473
474    e4_assert(right_idx<size());
475    if (right_idx==-1 || right_idx>=size()) right_idx = size()-1;
476
477    char *consensus_string = fill_id;
478
479#define PERCENT(part, all)      ((100*(part))/(all))
480#define MAX_BASES_TABLES 41     //25
481
482    e4_assert(used_bases_tables<=MAX_BASES_TABLES);     // this is correct for DNA/RNA -> build_consensus_string() must be corrected for AMI/PRO
483
484    if (sequences) {
485        for (i=left_idx; i<=right_idx; i++) {
486            int bases = 0; // count of all bases together
487            int base[MAX_BASES_TABLES]; // count of specific base
488            int j;
489            int max_base = -1; // maximum count of specific base
490            int max_j = -1; // index of this base
491
492            for (j=0; j<used_bases_tables; j++) {
493                base[j] = linear_table(j)[i];
494                if (!ADPP_IS_ALIGN_CHARACTER(index_to_upperChar(j))) {
495                    bases += base[j];
496                    if (base[j]>max_base) { // search for most used base
497                        max_base = base[j];
498                        max_j = j;
499                    }
500                }
501            }
502
503            int gaps = sequences-bases; // count of gaps
504
505            // What to do with gaps?
506
507            if (gaps == sequences) {
508                consensus_string[i] = '=';
509            }
510            else if (BK_countgaps && PERCENT(gaps, sequences)>=BK_gapbound) {
511                consensus_string[i] = '-';
512            }
513            else {
514                // Simplify using IUPAC :
515
516                char kchar;     // character for consensus
517                int  kcount;    // count this character
518
519                if (BK_group) { // group -> iupac
520                    if (IS_NUCLEOTIDE()) {
521                        int no_of_bases = 0; // count of different bases used to create iupac
522                        char used_bases[MAX_BASES_TABLES+1]; // string containing those bases
523
524                        kcount = 0;
525                        for (j=0; j<used_bases_tables; j++) {
526                            int bchar = index_to_upperChar(j);
527
528                            if (!ADPP_IS_ALIGN_CHARACTER(bchar)) {
529                                if (PERCENT(base[j], sequences)>=BK_considbound) {
530                                    used_bases[no_of_bases++] = index_to_upperChar(j);
531                                    kcount += base[j];
532                                }
533                            }
534                        }
535                        used_bases[no_of_bases] = 0;
536                        kchar = ED4_encode_iupac(used_bases, ED4_ROOT->alignment_type);
537                    }
538                    else {
539                        e4_assert(IS_AMINO());
540
541                        int group_count[ED4_IUPAC_GROUPS];
542
543                        for (j=0; j<ED4_IUPAC_GROUPS; j++) {
544                            group_count[j] = 0;
545                        }
546                        for (j=0; j<used_bases_tables; j++) {
547                            unsigned char bchar = index_to_upperChar(j);
548
549                            if (!ADPP_IS_ALIGN_CHARACTER(bchar)) {
550                                if (PERCENT(base[j], sequences)>=BK_considbound) {
551                                    group_count[AWT_iupac_group[toupper(bchar)-'A']] += base[j];
552                                }
553                            }
554                        }
555
556                        kcount = 0;
557                        int bestGroup = 0;
558                        for (j=0; j<ED4_IUPAC_GROUPS; j++) {
559                            if (group_count[j]>kcount) {
560                                bestGroup = j;
561                                kcount = group_count[j];
562                            }
563                        }
564
565                        kchar = "?ADHIF"[bestGroup];
566                    }
567                }
568                else {
569                    e4_assert(max_base); // expect at least one base to occur
570                    kchar = index_to_upperChar(max_j);
571                    kcount = max_base;
572                }
573
574                // show as upper or lower case ?
575
576                int percent = PERCENT(kcount, sequences);
577
578                if (percent>=BK_upper) {
579                    consensus_string[i] = kchar;
580                }
581                else if (percent>=BK_lower){
582                    consensus_string[i] = tolower(kchar);
583                }
584                else {
585                    consensus_string[i] = '.';
586                }
587            }
588        }
589    }
590    else {
591        for (i=left_idx; i<=right_idx; i++) {
592            consensus_string[i] = '?';
593        }
594    }
595
596
597#undef PERCENT
598
599    return consensus_string;
600}
601
602// --------------------------------------------------------------------------------
603//              ED4_char_table::
604// --------------------------------------------------------------------------------
605
606// bool ED4_char_table::tables_are_valid = true;
607bool ED4_char_table::initialized = false;
608unsigned char ED4_char_table::char_to_index_tab[MAXCHARTABLE];
609unsigned char *ED4_char_table::upper_index_chars = 0;
610unsigned char *ED4_char_table::lower_index_chars = 0;
611int ED4_char_table::used_bases_tables = 0;
612
613inline void ED4_char_table::set_char_to_index(unsigned char c, int index)
614{
615    e4_assert(index>=0 && index<used_bases_tables);
616    char_to_index_tab[upper_index_chars[index] = toupper(c)] = index;
617    char_to_index_tab[lower_index_chars[index] = tolower(c)] = index;
618}
619unsigned char ED4_char_table::index_to_upperChar(int index) const
620{
621    return upper_index_chars[index];
622}
623unsigned char ED4_char_table::index_to_lowerChar(int index) const
624{
625    return lower_index_chars[index];
626}
627
628void ED4_char_table::expand_tables() {
629    int i;
630    for (i=0; i<used_bases_tables; i++) {
631        linear_table(i).expand_table_entry_size();
632    }
633}
634
635ED4_char_table::ED4_char_table(int maxseqlength)
636{
637    memset((char*)this,0,sizeof(*this));
638
639    if (!initialized) {
640        const char *groups = 0;
641        char *align_string = ED4_ROOT->aw_root->awar_string(ED4_AWAR_GAP_CHARS)->read_string();
642        used_bases_tables = strlen(align_string);
643
644        if (IS_NUCLEOTIDE()) {
645            if (IS_RNA()) {
646                groups = "A,C,G,TU,MRWSYKVHDBN,";
647            }
648            else {
649                groups = "A,C,G,UT,MRWSYKVHDBN,";
650            }
651        }
652        else {
653            e4_assert(IS_AMINO());
654            groups = "P,A,G,S,T,Q,N,E,D,B,Z,H,K,R,L,I,V,M,F,Y,W,";
655        }
656
657        e4_assert(groups);
658
659        int i;
660
661        for (i=0; groups[i]; i++) {
662            if (groups[i]==',') {
663                used_bases_tables++;
664            }
665        }
666
667        lower_index_chars = new unsigned char[used_bases_tables];
668        upper_index_chars = new unsigned char[used_bases_tables];
669
670        int idx = 0;
671        unsigned char init_val = used_bases_tables-1; // map all unknown stuff to last table
672        memset(char_to_index_tab, init_val, MAXCHARTABLE*sizeof(*char_to_index_tab));
673
674        for (i=0; groups[i]; i++) {
675            if (groups[i]==',') {
676                idx++;
677            }
678            else {
679                e4_assert(isupper(groups[i]));
680                set_char_to_index(groups[i], idx);
681            }
682        }
683
684        const char *align_string_ptr = align_string;
685        while (1) {
686            char c = *align_string_ptr++;
687            if (!c) break;
688            set_char_to_index(c, idx++);
689        }
690
691        e4_assert(idx==used_bases_tables);
692        initialized = true;
693        free(align_string);
694    }
695
696    bases_table = new ED4_bases_table_ptr[used_bases_tables];
697
698    int i;
699    for (i=0; i<used_bases_tables; i++) {
700        bases_table[i] = new ED4_bases_table(maxseqlength);
701    }
702
703    sequences = 0;
704}
705
706void ED4_char_table::init(int maxseqlength)
707{
708    int i;
709    for (i=0; i<used_bases_tables; i++) {
710        linear_table(i).init(maxseqlength);
711    }
712
713    sequences = 0;
714}
715
716void ED4_char_table::bases_and_gaps_at(int column, int *bases, int *gaps) const
717{
718    int i,
719        b = 0,
720        g = 0;
721
722    for (i=0; i<used_bases_tables; i++) {
723        char c = upper_index_chars[i];
724
725        if (ADPP_IS_ALIGN_CHARACTER(c)) {
726            g += table(c)[column];
727        }
728        else {
729            b += table(c)[column];
730        }
731    }
732
733    if (bases) *bases = b;
734    if (gaps)  *gaps  = g;
735}
736
737ED4_char_table::~ED4_char_table()
738{
739    int i;
740    for (i=0; i<used_bases_tables; i++) {
741        delete bases_table[i];
742    }
743
744    delete [] bases_table;
745}
746
747int ED4_char_table::changed_range(const ED4_char_table& other, int *startPtr, int *endPtr) const
748{
749    int i;
750    int Size = size();
751    int start = Size-1;
752    int end = 0;
753
754    e4_assert(Size==other.size());
755    for (i=0; i<used_bases_tables; i++) {
756        if (linear_table(i).firstDifference(other.linear_table(i), 0, start, &start)) {
757            if (end<start) {
758                end = start;
759            }
760            linear_table(i).lastDifference(other.linear_table(i), end+1, Size-1, &end);
761
762            for (; i<used_bases_tables; i++) {
763                linear_table(i).firstDifference(other.linear_table(i), 0, start-1, &start);
764                if (end<start) {
765                    end = start;
766                }
767                linear_table(i).lastDifference(other.linear_table(i), end+1, Size-1, &end);
768            }
769
770            *startPtr = start;
771            *endPtr = end;
772            e4_assert(start<=end);
773            return 1;
774        }
775    }
776    return 0;
777}
778void ED4_char_table::add(const ED4_char_table& other)
779{
780    if (other.ignore) return;
781    if (other.size()==0) return;
782    prepare_to_add_elements(other.sequences);
783    add(other, 0, other.size()-1);
784}
785void ED4_char_table::add(const ED4_char_table& other, int start, int end)
786{
787    if (other.ignore) return;
788
789    test();
790    other.test();
791
792    e4_assert(start<=end);
793
794    int i;
795    for (i=0; i<used_bases_tables; i++) {
796        linear_table(i).add(other.linear_table(i), start, end);
797    }
798
799    sequences += other.sequences;
800
801    test();
802}
803
804void ED4_char_table::sub(const ED4_char_table& other)
805{
806    if (other.ignore) return;
807    sub(other, 0, other.size()-1);
808}
809
810void ED4_char_table::sub(const ED4_char_table& other, int start, int end)
811{
812    if (other.ignore) return;
813
814    test();
815    other.test();
816    e4_assert(start<=end);
817
818    int i;
819    for (i=0; i<used_bases_tables; i++) {
820        linear_table(i).sub(other.linear_table(i), start, end);
821    }
822
823    sequences -= other.sequences;
824
825    test();
826}
827
828void ED4_char_table::sub_and_add(const ED4_char_table& Sub, const ED4_char_table& Add)
829{
830    int start, end;
831
832    test();
833
834    if (Sub.ignore) {
835        e4_assert(Add.ignore);
836        return;
837    }
838
839    Sub.test();
840    Add.test();
841
842    if (Sub.changed_range(Add, &start, &end)) {
843        prepare_to_add_elements(Add.added_sequences()-Sub.added_sequences());
844        sub_and_add(Sub, Add, start, end);
845    }
846
847    test();
848}
849void ED4_char_table::sub_and_add(const ED4_char_table& Sub, const ED4_char_table& Add, int start, int end)
850{
851    test();
852    Sub.test();
853    Add.test();
854
855    e4_assert(!Sub.ignore && !Add.ignore);
856    e4_assert(start<=end);
857
858    int i;
859    for (i=0; i<used_bases_tables; i++) {
860        linear_table(i).sub_and_add(Sub.linear_table(i), Add.linear_table(i), start, end);
861    }
862
863    test();
864}
865
866int ED4_char_table::changed_range(const char *string1, const char *string2, int min_len, int *start, int *end)
867{
868    const unsigned long *range1 = (const unsigned long *)string1;
869    const unsigned long *range2 = (const unsigned long *)string2;
870    const int step = sizeof(*range1);
871    int l = min_len/step;
872    int r = min_len%step;
873    int i;
874    int j;
875    int k;
876
877    for (i=0; i<l; i++) {       // search wordwise (it's faster)
878        if (range1[i] != range2[i]) {
879            k = i*step;
880            for (j=0; j<step; j++) {
881                if (string1[k+j] != string2[k+j]) {
882                    *start = *end = k+j;
883                    break;
884                }
885            }
886
887            break;
888        }
889    }
890
891    k = l*step;
892    if (i==l) {         // no difference found in word -> look at rest
893        for (j=0; j<r; j++) {
894            if (string1[k+j] != string2[k+j]) {
895                *start = *end = k+j;
896                break;
897            }
898        }
899
900        if (j==r) {     // the strings are equal
901            return 0;
902        }
903    }
904
905    for (j=r-1; j>=0; j--) {    // search rest backwards
906        if (string1[k+j] != string2[k+j]) {
907            *end = k+j;
908            break;
909        }
910    }
911
912    if (j==-1) {                // not found in rest -> search words backwards
913        int m = *start/step;
914        for (i=l-1; i>=m; i--) {
915            if (range1[i] != range2[i]) {
916                k = i*step;
917                for (j=step-1; j>=0; j--) {
918                    if (string1[k+j] != string2[k+j]) {
919                        *end = k+j;
920                        break;
921                    }
922                }
923                break;
924            }
925        }
926    }
927
928    e4_assert(*start<=*end);
929    return 1;
930}
931
932void ED4_char_table::add(const char *scan_string, int len)
933{
934    test();
935
936    prepare_to_add_elements(1);
937
938    int i;
939    int sz = size();
940
941    if (get_table_entry_size()==SHORT_TABLE_ELEM_SIZE) {
942        for (i=0; i<len; i++) {
943            unsigned char c = scan_string[i];
944            if (!c) break;
945            table(c).inc_short(i);
946        }
947        ED4_bases_table& t = table('.');
948        for (; i<sz; i++) {
949            t.inc_short(i);
950        }
951    }
952    else {
953        for (i=0; i<len; i++) {
954            unsigned char c = scan_string[i];
955            if (!c) break;
956            table(c).inc_long(i);
957        }
958        ED4_bases_table& t = table('.');
959        for (; i<sz; i++) {
960            t.inc_long(i);
961        }
962    }
963
964    sequences++;
965
966    test();
967}
968
969void ED4_char_table::sub(const char *scan_string, int len)
970{
971    test();
972
973    int i;
974    int sz = size();
975
976    if (get_table_entry_size()==SHORT_TABLE_ELEM_SIZE) {
977        for (i=0; i<len; i++) {
978            unsigned char c = scan_string[i];
979            if (!c) break;
980            table(c).dec_short(i);
981        }
982        ED4_bases_table& t = table('.');
983        for (; i<sz; i++) {
984            t.dec_short(i);
985        }
986    }
987    else {
988        for (i=0; i<len; i++) {
989            unsigned char c = scan_string[i];
990            if (!c) break;
991            table(c).dec_long(i);
992        }
993        ED4_bases_table& t = table('.');
994        for (; i<sz; i++) {
995            t.dec_long(i);
996        }
997    }
998
999    sequences--;
1000
1001    test();
1002}
1003
1004void ED4_char_table::sub_and_add(const char *old_string, const char *new_string, int start, int end)
1005{
1006    test();
1007    e4_assert(start<=end);
1008
1009    int i;
1010    ED4_bases_table& t = table('.');
1011
1012    if (get_table_entry_size()==SHORT_TABLE_ELEM_SIZE) {
1013        for (i=start; i<=end; i++) {
1014            unsigned char o = old_string[i];
1015            unsigned char n = new_string[i];
1016
1017            if (!o) {
1018                for (; n && i<=end; i++) {
1019                    n = new_string[i];
1020                    table(n).inc_short(i);
1021                    t.dec_short(i);
1022                }
1023            }
1024            else if (!n) {
1025                for (; o && i<=end; i++) {
1026                    o = old_string[i];
1027                    table(o).dec_short(i);
1028                    t.inc_short(i);
1029                }
1030
1031            }
1032            else if (o!=n) {
1033                table(o).dec_short(i);
1034                table(n).inc_short(i);
1035
1036            }
1037        }
1038    }
1039    else {
1040        for (i=start; i<=end; i++) {
1041            unsigned char o = old_string[i];
1042            unsigned char n = new_string[i];
1043
1044            if (!o) {
1045                for (; n && i<=end; i++) {
1046                    n = new_string[i];
1047                    table(n).inc_long(i);
1048                    t.dec_long(i);
1049                }
1050            }
1051            else if (!n) {
1052                for (; o && i<=end; i++) {
1053                    o = old_string[i];
1054                    table(o).dec_long(i);
1055                    t.inc_long(i);
1056                }
1057
1058            }
1059            else if (o!=n) {
1060                table(o).dec_long(i);
1061                table(n).inc_long(i);
1062            }
1063        }
1064    }
1065
1066    test();
1067}
1068
1069void ED4_char_table::change_table_length(int new_length)
1070{
1071    int c;
1072
1073    //     int bases1, gaps1;
1074    //     bases_and_gaps_at(0, &bases1, &gaps1);
1075
1076    //     int table_thickness = bases1+gaps1;
1077    //     bool gaps_inserted = false;
1078
1079    // test(); fails because MAXSEQUENCECHARACTERLENGTH is already incremented
1080
1081    for (c=0; c<used_bases_tables; c++) {
1082        //         int default_entry = 0;
1083        //         if (!gaps_inserted && ADPP_IS_ALIGN_CHARACTER(upper_index_chars[c])) {
1084        //             default_entry = table_thickness;
1085        //             gaps_inserted = true;
1086        //         }
1087        //         linear_table(c).change_table_length(new_length, default_entry);
1088        linear_table(c).change_table_length(new_length, 0);
1089    }
1090
1091    test();
1092}
1093
1094//  --------------
1095//      tests:
1096//  --------------
1097
1098#if defined(TEST_CHAR_TABLE_INTEGRITY) || defined(ASSERTION_USED)
1099
1100bool ED4_char_table::empty() const
1101{
1102    int i;
1103    for (i=0; i<used_bases_tables; i++) {
1104        if (!linear_table(i).empty()) {
1105            return false;
1106        }
1107    }
1108    return true;
1109}
1110
1111bool ED4_char_table::ok() const
1112{
1113    if (empty()) return true;
1114    if (is_ignored()) return true;
1115
1116    if (sequences<0) {
1117        fprintf(stderr, "Negative # of sequences (%i) in ED4_char_table\n", sequences);
1118        return false;
1119    }
1120
1121    int i;
1122    for (i=0; i<MAXSEQUENCECHARACTERLENGTH; i++) {
1123        int bases;
1124        int gaps;
1125
1126        bases_and_gaps_at(i, &bases, &gaps);
1127
1128        if (!bases && !gaps) { // this occurs after insert column
1129            int j;
1130            for (j=i+1; j<MAXSEQUENCECHARACTERLENGTH; j++) {    // test if we find any bases till end of table !!!
1131
1132                bases_and_gaps_at(j, &bases, 0);
1133                if (bases) { // bases found -> empty position was illegal
1134                    fprintf(stderr, "Zero in ED4_char_table at column %i\n", i);
1135                    return false;
1136                }
1137            }
1138            break;
1139        }
1140        else {
1141            if ((bases+gaps)!=sequences) {
1142                fprintf(stderr, "bases+gaps should be equal to # of sequences at column %i\n", i);
1143                return false;
1144            }
1145        }
1146    }
1147
1148    return true;
1149}
1150
1151#endif // TEST_CHAR_TABLE_INTEGRITY || ASSERTION_USED
1152
1153#if defined(TEST_CHAR_TABLE_INTEGRITY)
1154
1155//  ------------------------------------------
1156//      void ED4_char_table::test() const
1157//  ------------------------------------------
1158void ED4_char_table::test() const {
1159   
1160    if (!ok()) {
1161        GBK_terminate("ED4_char_table::test() failed");
1162    }
1163}
1164
1165#endif // TEST_CHAR_TABLE_INTEGRITY
Note: See TracBrowser for help on using the repository browser.