root/trunk/ARBDB/adseqcompr.cxx

Revision 8607, 31.8 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8135] [8136] [8137] [8138] [8139] [8140] [8141] [8142] [8143] [8144] [8222]
this revives the reverted patches [8129] [8130] [8131] [8132]

  • fixes
    • some free/delete mismatches
    • wrong definition of ORF objects (Level was no bit value)
    • amino consensus (failed for columns only containing 'C')
  • rename
    • AA_sequence_term -> orf_term
    • ED4_sequence_terminal_basic -> ED4_abstract_sequence_terminal
  • cleaned up hierarchy dumps
  • tweaked is_terminal()/to_terminal()
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adseqcompr.cxx                                    //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <arbdbt.h>
12#include <arb_progress.h>
13
14#include "gb_key.h"
15
16// --------------------------------------------------------------------------------
17
18#define MAX_SEQUENCE_PER_MASTER 50 // was 18 till May 2008
19
20#if defined(DEBUG)
21// don't do optimize, only create tree and save to DB
22// #define SAVE_COMPRESSION_TREE_TO_DB
23#endif // DEBUG
24
25// --------------------------------------------------------------------------------
26
27struct CompressionTree {
28    GBT_VTAB_AND_TREE_ELEMENTS(CompressionTree);
29
30    int index;                  // master(inner nodes) or sequence(leaf nodes) index
31    int sons;                   // sons with sequence or masters (in subtree)
32};
33
34struct Consensus {
35    int            len;
36    char           used[256];
37    unsigned char *con[256];
38};
39
40struct Sequence {
41    GBDATA *gbd;
42    int     master;
43};
44
45struct MasterSequence {
46    GBDATA *gbd;
47    int     master;
48};
49
50// --------------------------------------------------------------------------------
51
52static Consensus *g_b_new_Consensus(long len) {
53    Consensus     *gcon = (Consensus *)GB_calloc(sizeof(*gcon), 1);
54    unsigned char *data = (unsigned char *)GB_calloc(sizeof(char)*256, len);
55
56    gcon->len = len;
57
58    for (int i=0; i<256; i++) {
59        gcon->con[i] = data + len*i;
60    }
61    return gcon;
62}
63
64
65static void g_b_delete_Consensus(Consensus *gcon) {
66    free(gcon->con[0]);
67    free(gcon);
68}
69
70
71static void g_b_Consensus_add(Consensus *gcon, unsigned char *seq, long seq_len) {
72    int            i;
73    int            li;
74    int            c;
75    unsigned char *s;
76    int            last;
77    unsigned char *p;
78    int            eq_count;
79    const int      max_priority = 255/MAX_SEQUENCE_PER_MASTER; // No overflow possible
80
81    gb_assert(max_priority >= 1);
82
83    if (seq_len > gcon->len) seq_len = gcon->len;
84
85    // Search for runs
86    s = seq;
87    last = 0;
88    eq_count = 0;
89    for (li = i = 0; i < seq_len; i++) {
90        c = *(s++);
91        if (c == last) {
92            continue;
93        }
94        else {
95        inc_hits :
96            eq_count = i-li;
97            gcon->used[c] = 1;
98            p = gcon->con[last];
99            last = c;
100            if (eq_count <= GB_RUNLENGTH_SIZE) {
101                c = max_priority;
102                while (li < i) p[li++] += c;
103            }
104            else {
105                c = max_priority * (GB_RUNLENGTH_SIZE) / eq_count;
106                if (c) {
107                    while (li < i) p[li++] += c;
108                }
109                else {
110                    while (li < i) p[li++] |= 1;
111                }
112            }
113        }
114    }
115    if (li<seq_len) {
116        c = last;
117        i = seq_len;
118        goto inc_hits;
119    }
120}
121
122static char *g_b_Consensus_get_sequence(Consensus *gcon) {
123    int pos;
124    unsigned char *s;
125    unsigned char *max = (unsigned char *)GB_calloc(sizeof(char), gcon->len);
126    int c;
127    char *seq = (char *)GB_calloc(sizeof(char), gcon->len+1);
128
129    memset(seq, '@', gcon->len);
130
131    for (c = 1; c<256; c++) { // Find maximum frequency of non run
132        if (!gcon->used[c]) continue;
133        s = gcon->con[c];
134        for (pos = 0; pos<gcon->len; pos++) {
135            if (*s > max[pos]) {
136                max[pos] = *s;
137                seq[pos] = c;
138            }
139            s++;
140        }
141    }
142    free(max);
143    return seq;
144}
145
146
147static int g_b_count_leafs(CompressionTree *node) {
148    if (node->is_leaf) return 1;
149    node->gb_node = 0;
150    return (g_b_count_leafs(node->leftson) + g_b_count_leafs(node->rightson));
151}
152
153static void g_b_put_sequences_in_container(CompressionTree *ctree, Sequence *seqs, MasterSequence **masters, Consensus *gcon) {
154    if (ctree->is_leaf) {
155        if (ctree->index >= 0) {
156            GB_CSTR data = GB_read_char_pntr(seqs[ctree->index].gbd);
157            long    len  = GB_read_string_count(seqs[ctree->index].gbd);
158            g_b_Consensus_add(gcon, (unsigned char *)data, len);
159        }
160    }
161    else if (ctree->index<0) {
162        g_b_put_sequences_in_container(ctree->leftson, seqs, masters, gcon);
163        g_b_put_sequences_in_container(ctree->rightson, seqs, masters, gcon);
164    }
165    else {
166        GB_CSTR data = GB_read_char_pntr(masters[ctree->index]->gbd);
167        long    len  = GB_read_string_count(masters[ctree->index]->gbd);
168        g_b_Consensus_add(gcon, (unsigned char *)data, len);
169    }
170}
171
172static void g_b_create_master(CompressionTree *node, Sequence *seqs, MasterSequence **masters, int my_master, const char *ali_name, long seq_len, arb_progress& progress) {
173    if (node->is_leaf) {
174        if (node->index >= 0) {
175            GBDATA *gb_data = GBT_read_sequence(node->gb_node, ali_name);
176
177            seqs[node->index].gbd    = gb_data;
178            seqs[node->index].master = my_master;
179        }
180    }
181    else {
182        if (progress.aborted()) return;
183       
184        if (node->index>=0) {
185            masters[node->index]->master = my_master;
186            my_master = node->index;
187        }
188        g_b_create_master(node->leftson, seqs, masters, my_master, ali_name, seq_len, progress);
189        g_b_create_master(node->rightson, seqs, masters, my_master, ali_name, seq_len, progress);
190        if (node->index>=0 && !progress.aborted()) { // build me
191            char      *data;
192            Consensus *gcon = g_b_new_Consensus(seq_len);
193
194            g_b_put_sequences_in_container(node->leftson, seqs, masters, gcon);
195            g_b_put_sequences_in_container(node->rightson, seqs, masters, gcon);
196
197            data = g_b_Consensus_get_sequence(gcon);
198
199            GB_write_string(masters[node->index]->gbd, data);
200            GB_write_security_write(masters[node->index]->gbd, 7);
201
202            g_b_delete_Consensus(gcon);
203            free(data);
204
205            ++progress;
206        }
207    }
208}
209
210// -------------------------------------
211//      distribute master sequences
212
213static void subtract_sons_from_tree(CompressionTree *node, int subtract) {
214    while (node) {
215        node->sons -= subtract;
216        node        = node->father;
217    }
218}
219
220static int set_masters_with_sons(CompressionTree *node, int wantedSons, int *mcount) {
221    if (!node->is_leaf) {
222        if (node->sons == wantedSons) {
223            // insert new master
224            gb_assert(node->index == -1);
225            node->index = *mcount;
226            (*mcount)++;
227
228            subtract_sons_from_tree(node->father, node->sons-1);
229            node->sons = 1;
230        }
231        else if (node->sons>wantedSons) {
232            int lMax = set_masters_with_sons(node->leftson,  wantedSons, mcount);
233            int rMax = set_masters_with_sons(node->rightson, wantedSons, mcount);
234
235            int maxSons = lMax<rMax ? rMax : lMax;
236            if (node->sons <= MAX_SEQUENCE_PER_MASTER && node->sons>maxSons) {
237                maxSons = node->sons;
238            }
239            return maxSons;
240        }
241    }
242    return node->sons <= MAX_SEQUENCE_PER_MASTER ? node->sons : 0;
243}
244
245static int maxCompressionSteps(CompressionTree *node) {
246    if (node->is_leaf) {
247        return 0;
248    }
249
250    int left  = maxCompressionSteps(node->leftson);
251    int right = maxCompressionSteps(node->rightson);
252
253#if defined(SAVE_COMPRESSION_TREE_TO_DB)
254    freenull(node->name);
255    if (node->index2 != -1) {
256        node->name = GBS_global_string_copy("master_%03i", node->index2);
257    }
258#endif // SAVE_COMPRESSION_TREE_TO_DB
259
260    return (left>right ? left : right) + (node->index == -1 ? 0 : 1);
261}
262
263static int init_indices_and_count_sons(CompressionTree *node, int *scount, const char *ali_name) {
264    if (node->is_leaf) {
265        if (node->gb_node == 0 || !GBT_read_sequence(node->gb_node, (char *)ali_name)) {
266            node->index = -1;
267            node->sons  = 0;
268        }
269        else {
270            node->index = *scount;
271            node->sons  = 1;
272            (*scount)++;
273        }
274    }
275    else {
276        node->index = -1;
277        node->sons  =
278            init_indices_and_count_sons(node->leftson, scount, ali_name) +
279            init_indices_and_count_sons(node->rightson, scount, ali_name);
280    }
281    return node->sons;
282}
283
284static void distribute_masters(CompressionTree *tree, int *mcount, int *max_masters) {
285    int wantedSons = MAX_SEQUENCE_PER_MASTER;
286    while (wantedSons >= 2) {
287        int maxSons = set_masters_with_sons(tree, wantedSons, mcount);
288        wantedSons = maxSons;
289    }
290    gb_assert(tree->sons == 1);
291
292    gb_assert(tree->index != -1);
293    *max_masters = maxCompressionSteps(tree);
294}
295
296// --------------------------------------------------------------------------------
297
298inline long g_b_read_number2(const unsigned char **s) {
299    unsigned int c0, c1, c2, c3, c4;
300    c0 = (*((*s)++));
301    if (c0 & 0x80) {
302        c1 = (*((*s)++));
303        if (c0 & 0x40) {
304            c2 = (*((*s)++));
305            if (c0 & 0x20) {
306                c3 = (*((*s)++));
307                if (c0 &0x10) {
308                    c4 = (*((*s)++));
309                    return c4 | (c3<<8) | (c2<<16) | (c1<<8);
310                }
311                else {
312                    return (c3) | (c2<<8) | (c1<<16) | ((c0 & 0x0f)<<24);
313                }
314            }
315            else {
316                return (c2) | (c1<<8) | ((c0 & 0x1f)<<16);
317            }
318        }
319        else {
320            return (c1) | ((c0 & 0x3f)<<8);
321        }
322    }
323    else {
324        return c0;
325    }
326}
327
328inline void g_b_put_number2(int i, unsigned char **s) {
329    int j;
330    if (i< 0x80) { *((*s)++)=i; return; }
331    if (i<0x4000) {
332        j = (i>>8) | 0x80;
333        *((*s)++)=j;
334        *((*s)++)=i;
335    }
336    else if (i<0x200000) {
337        j = (i>>16) | 0xC0;
338        *((*s)++)=j;
339        j = (i>>8);
340        *((*s)++)=j;
341        *((*s)++)=i;
342    }
343    else if (i<0x10000000) {
344        j = (i>>24) | 0xE0;
345        *((*s)++)=j;
346        j = (i>>16);
347        *((*s)++)=j;
348        j = (i>>8);
349        *((*s)++)=j;
350        *((*s)++)=i;
351    }
352}
353
354
355static char *gb_compress_seq_by_master(const char *master, int master_len, int master_index,
356                                       GBQUARK q, const char *seq, long seq_len,
357                                       long *memsize, int old_flag) {
358    unsigned char *buffer;
359    int            rest = 0;
360    unsigned char *d;
361    int            i, cs, cm;
362    int            last;
363    long           len  = seq_len;
364
365    d = buffer = (unsigned char *)GB_give_other_buffer(seq, seq_len);
366
367    if (seq_len > master_len) {
368        rest = seq_len - master_len;
369        len = master_len;
370    }
371
372    last = -1000;       // Convert Sequence relative to Master
373    for (i = len; i>0; i--) {
374        cm = *(master++);
375        cs = *(seq++);
376        if (cm==cs && cs != last) {
377            *(d++) = 0;
378            last = 1000;
379        }
380        else {
381            *(d++) = cs;
382            last = cs;
383        }
384    }
385    for (i = rest; i>0; i--) {
386        *(d++) = *(seq++);
387    }
388
389    {               // Append run length compression method
390        unsigned char *buffer2;
391        unsigned char *dest2;
392        buffer2 = dest2 = (unsigned char *)GB_give_other_buffer((char *)buffer, seq_len+100);
393        *(dest2++) = GB_COMPRESSION_SEQUENCE | old_flag;
394
395        g_b_put_number2(master_index, &dest2); // Tags
396        g_b_put_number2(q, &dest2);
397
398        gb_compress_equal_bytes_2((char *)buffer, seq_len, memsize, (char *)dest2); // append runlength compressed sequences to tags
399
400        *memsize = *memsize + (dest2-buffer2);
401        return (char *)buffer2;
402    }
403}
404
405static char *gb_compress_sequence_by_master(GBDATA *gbd, const char *master, int master_len, int master_index,
406                                            GBQUARK q, const char *seq, int seq_len, long *memsize)
407{
408    long  size;
409    char *is  = gb_compress_seq_by_master(master, master_len, master_index, q, seq, seq_len, &size, GB_COMPRESSION_LAST);
410    char *res = gb_compress_data(gbd, 0, is, size, memsize, ~(GB_COMPRESSION_DICTIONARY|GB_COMPRESSION_SORTBYTES|GB_COMPRESSION_RUNLENGTH), true);
411    return res;
412}
413
414static GB_ERROR compress_sequence_tree(GBDATA *gb_main, CompressionTree *tree, const char *ali_name) {
415    GB_ERROR error      = 0;
416    long     ali_len    = GBT_get_alignment_len(gb_main, ali_name);
417    int      main_clock = GB_read_clock(gb_main);
418
419    GB_ERROR warning = NULL;
420
421    if (ali_len<0) {
422        warning = GBS_global_string("Skipping alignment '%s' (not a valid alignment; len=%li).", ali_name, ali_len);
423    }
424    else {
425        int leafcount = g_b_count_leafs(tree);
426        if (!leafcount) {
427            error = "Tree is empty";
428        }
429        else {
430            arb_progress tree_progress("Compressing sequences", 4);
431           
432            // Distribute masters in tree
433            int mastercount   = 0;
434            int max_compSteps = 0; // in one branch
435            int seqcount      = 0;
436
437            init_indices_and_count_sons(tree, &seqcount, ali_name);
438            if (!seqcount) {
439                warning = GBS_global_string("Tree contains no sequences with data in '%s'\n"
440                                            "Skipping compression for this alignment",
441                                            ali_name);
442            }
443            else {
444                distribute_masters(tree, &mastercount, &max_compSteps);
445
446#if defined(SAVE_COMPRESSION_TREE_TO_DB)
447                {
448                    error = GBT_link_tree((GBT_TREE*)tree, gb_main, 0, NULL, NULL);
449                    if (!error) error = GBT_write_tree(gb_main, 0, "tree_compression_new", (GBT_TREE*)tree);
450                    GB_information("Only generated compression tree (do NOT save DB anymore)");
451                    return error;
452                }
453#endif // SAVE_COMPRESSION_TREE_TO_DB
454
455                // detect degenerated trees
456                {
457                    int min_masters   = ((seqcount-1)/MAX_SEQUENCE_PER_MASTER)+1;
458                    int min_compSteps = 1;
459                    {
460                        int m = min_masters;
461                        while (m>1) {
462                            m            = ((m-1)/MAX_SEQUENCE_PER_MASTER)+1;
463                            min_masters += m;
464                            min_compSteps++;
465                        }
466                    }
467
468                    int acceptable_masters   = (3*min_masters)/2; // accept 50% overhead
469                    int acceptable_compSteps = 11*min_compSteps; // accept 1000% overhead
470
471                    if (mastercount>acceptable_masters || max_compSteps>acceptable_compSteps) {
472                        GB_warningf("Tree is ill-suited for compression (cause of deep branches)\n"
473                                    "                    Used tree   Optimal tree   Overhead\n"
474                                    "Compression steps       %5i          %5i      %4i%% (speed)\n"
475                                    "Master sequences        %5i          %5i      %4i%% (size)\n"
476                                    "If you like to restart with a better tree,\n"
477                                    "press 'Abort' to stop compression",
478                                    max_compSteps, min_compSteps, (100*max_compSteps)/min_compSteps-100,
479                                    mastercount, min_masters, (100*mastercount)/min_masters-100);
480                    }
481                }
482
483                gb_assert(mastercount>0);
484            }
485
486            if (!warning) {
487                GBDATA              *gb_master_ali     = 0;
488                GBDATA              *old_gb_master_ali = 0;
489                Sequence            *seqs              = 0;
490                GB_MAIN_TYPE        *Main              = GB_MAIN(gb_main);
491                GBQUARK              ali_quark         = gb_find_or_create_quark(Main, ali_name);
492                unsigned long long   sumorg            = 0;
493                unsigned long long   sumold            = 0;
494                unsigned long long   sumnew            = 0;
495                MasterSequence     **masters           = (MasterSequence **)GB_calloc(sizeof(*masters), leafcount);
496                int                  si;
497
498                {
499                    char *masterfoldername = GBS_global_string_copy("%s/@master_data/@%s", GB_SYSTEM_FOLDER, ali_name);
500                    old_gb_master_ali      = GB_search(gb_main, masterfoldername, GB_FIND);
501                    free(masterfoldername);
502                }
503
504                // create masters
505                if (!error) {
506                    {
507                        char   *master_data_name = GBS_global_string_copy("%s/@master_data", GB_SYSTEM_FOLDER);
508                        char   *master_name      = GBS_global_string_copy("@%s", ali_name);
509                        GBDATA *gb_master_data   = gb_search(gb_main, master_data_name, GB_CREATE_CONTAINER, 1);
510
511                        // create a master container, the old is deleted as soon as all sequences are compressed by the new method
512                        gb_master_ali = gb_create_container(gb_master_data, master_name);
513                        GB_write_security_delete(gb_master_ali, 7);
514
515                        free(master_name);
516                        free(master_data_name);
517                    }
518                    for (si = 0; si<mastercount; si++) {
519                        masters[si]      = (MasterSequence *)GB_calloc(sizeof(MasterSequence), 1);
520                        masters[si]->gbd = gb_create(gb_master_ali, "@master", GB_STRING);
521                    }
522                    seqs = (Sequence *)GB_calloc(sizeof(*seqs), leafcount);
523
524                    if (!error) {
525                        arb_progress progress("Building master sequences", mastercount);
526                        g_b_create_master(tree, seqs, masters, -1, ali_name, ali_len, progress);
527                       
528                        error = progress.error_if_aborted();
529                    }
530                }
531                tree_progress.inc_and_check_user_abort(error);
532
533                // Compress sequences in tree
534                if (!error) {
535                    arb_progress progress("Compressing sequences in tree", seqcount);
536
537                    for (si=0; si<seqcount && !error; si++) {
538                        int             mi     = seqs[si].master;
539                        MasterSequence *master = masters[mi];
540                        GBDATA         *gbd    = seqs[si].gbd;
541
542                        if (GB_read_clock(gbd) >= main_clock) {
543                            GB_warning("A species seems to be more than once in the tree");
544                        }
545                        else {
546                            char *seq        = GB_read_string(gbd);
547                            int   seq_len    = GB_read_string_count(gbd);
548                            long  sizen      = GB_read_memuse(gbd);
549                            char *seqm       = GB_read_string(master->gbd);
550                            int   master_len = GB_read_string_count(master->gbd);
551                            long  sizes;
552                            char *ss         = gb_compress_sequence_by_master(gbd, seqm, master_len, mi, ali_quark, seq, seq_len, &sizes);
553
554                            gb_write_compressed_pntr(gbd, ss, sizes, seq_len);
555                            sizes = GB_read_memuse(gbd); // check real usage
556
557                            sumnew += sizes;
558                            sumold += sizen;
559                            sumorg += seq_len;
560
561                            free(seqm);
562                            free(seq);
563                        }
564
565                        progress.inc_and_check_user_abort(error);
566                    }
567                }
568                tree_progress.inc_and_check_user_abort(error);
569
570                // Compress rest of sequences
571                if (!error) {
572                    int pass; // pass 1 : count species to compress, pass 2 : compress species
573                    int speciesNotInTree = 0;
574
575                    SmartPtr<arb_progress> progress;
576
577                    for (pass = 1; pass <= 2; ++pass) {
578                        GBDATA *gb_species_data = GBT_get_species_data(gb_main);
579                        GBDATA *gb_species;
580                        int     count           = 0;
581
582                        for (gb_species = GBT_first_species_rel_species_data(gb_species_data);
583                             gb_species;
584                             gb_species = GBT_next_species(gb_species))
585                        {
586                            GBDATA *gbd = GBT_read_sequence(gb_species, ali_name);
587
588                            if (!gbd) continue;
589                            if (GB_read_clock(gbd) >= main_clock) continue; // Compress only those which are not compressed by masters
590                            count++;
591                            if (pass == 2) {
592                                char *data    = GB_read_string(gbd);
593                                long  seq_len = GB_read_string_count(gbd);
594                                long  size    = GB_read_memuse(gbd);
595
596                                GB_write_string(gbd, "");
597                                GB_write_string(gbd, data);
598                                free(data);
599
600                                sumold += size;
601
602                                size = GB_read_memuse(gbd);
603                                sumnew += size;
604                                sumorg += seq_len;
605
606                                progress->inc_and_check_user_abort(error);
607                            }
608                        }
609                        if (pass == 1) {
610                            speciesNotInTree = count;
611                            if (speciesNotInTree>0) {
612                                progress = new arb_progress("Compressing sequences NOT in tree", speciesNotInTree);
613                            }
614                        }
615                    }
616                }
617                tree_progress.inc_and_check_user_abort(error);
618
619                if (!error) {
620                    arb_progress progress("Compressing master-sequences", mastercount);
621
622                    // Compress all masters
623                    for (si=0; si<mastercount; si++) {
624                        int mi = masters[si]->master;
625
626                        if (mi>0) { //  master available
627                            GBDATA *gbd = masters[si]->gbd;
628
629                            gb_assert(mi>si); // we don't want a recursion, because we cannot uncompress sequence compressed masters, Main->gb_master_data is wrong
630
631                            if (gb_read_nr(gbd) != si) { // Check database
632                                GB_internal_error("Sequence Compression: Master Index Conflict");
633                                error = GB_export_error("Sequence Compression: Master Index Conflict");
634                                break;
635                            }
636
637                            {
638                                MasterSequence *master     = masters[mi];
639                                char           *seqm       = GB_read_string(master->gbd);
640                                int             master_len = GB_read_string_count(master->gbd);
641                                char           *seq        = GB_read_string(gbd);
642                                int             seq_len    = GB_read_string_count(gbd);
643                                long            sizes;
644                                char           *ss         = gb_compress_sequence_by_master(gbd, seqm, master_len, mi, ali_quark, seq, seq_len, &sizes);
645
646                                gb_write_compressed_pntr(gbd, ss, sizes, seq_len);
647                                sumnew += sizes;
648
649                                free(seq);
650                                free(seqm);
651                            }
652
653                            progress.inc_and_check_user_abort(error);
654                        }
655                        else { // count size of top master
656                            GBDATA *gbd  = masters[si]->gbd;
657                            sumnew      += GB_read_memuse(gbd);
658
659                            progress.inc_and_check_user_abort(error);
660                        }
661                    }
662
663                    // count size of old master data
664                    if (!error) {
665                        GBDATA *gb_omaster;
666                        for (gb_omaster = GB_entry(old_gb_master_ali, "@master");
667                             gb_omaster;
668                             gb_omaster = GB_nextEntry(gb_omaster))
669                        {
670                            long size  = GB_read_memuse(gb_omaster);
671                            sumold    += size;
672                        }
673                    }
674
675                    if (!error) {
676                        char *sizeOrg = strdup(GBS_readable_size(sumorg, "b"));
677                        char *sizeOld = strdup(GBS_readable_size(sumold, "b"));
678                        char *sizeNew = strdup(GBS_readable_size(sumnew, "b"));
679
680                        GB_warningf("Alignment '%s':\n"
681                                    "    Uncompressed data:   %7s\n"
682                                    "    Old compressed data: %7s = %6.2f%%\n"
683                                    "    New compressed data: %7s = %6.2f%%",
684                                    ali_name, sizeOrg,
685                                    sizeOld, (100.0*sumold)/sumorg,
686                                    sizeNew, (100.0*sumnew)/sumorg);
687
688                        free(sizeNew);
689                        free(sizeOld);
690                        free(sizeOrg);
691                    }
692                }
693                tree_progress.inc_and_check_user_abort(error);
694
695                if (!error) {
696                    if (old_gb_master_ali) {
697                        error = GB_delete(old_gb_master_ali);
698                    }
699                    Main->keys[ali_quark].gb_master_ali = gb_master_ali;
700                }
701
702                // free data
703                free(seqs);
704                for (si=0; si<mastercount; si++) free(masters[si]);
705                free(masters);
706            }
707        }
708    }
709
710    if (warning) GB_information(warning);
711
712    return error;
713}
714
715GB_ERROR GBT_compress_sequence_tree2(GBDATA *gb_main, const char *tree_name, const char *ali_name) { // goes to header: __ATTR__USERESULT
716    // Compress sequences, call only outside a transaction
717    GB_ERROR      error = NULL;
718    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
719
720    if (Main->transaction>0) {
721        error = "Compress Sequences called during a running transaction";
722        GB_internal_error(error);
723    }
724    else {
725        GB_UNDO_TYPE prev_undo_type = GB_get_requested_undo_type(gb_main);
726
727        error = GB_request_undo_type(gb_main, GB_UNDO_KILL);
728        if (!error) {
729            error = GB_begin_transaction(gb_main);
730            if (!error) {
731                GB_push_my_security(gb_main);
732
733                if (!tree_name || !strlen(tree_name)) {
734                    tree_name = GBT_name_of_largest_tree(gb_main);
735                }
736
737                {
738                    CompressionTree *ctree   = (CompressionTree *)GBT_read_tree(gb_main, tree_name, -sizeof(CompressionTree));
739                    if (!ctree) error = GBS_global_string("Tree %s not found in database", tree_name);
740                    else {
741                        error             = GBT_link_tree((GBT_TREE *)ctree, gb_main, false, 0, 0);
742                        if (!error) error = compress_sequence_tree(gb_main, ctree, ali_name);
743                        GBT_delete_tree((GBT_TREE *)ctree);
744                    }
745                }
746                if (!error) GB_disable_quicksave(gb_main, "Database optimized");
747
748                GB_pop_my_security(gb_main);
749                error = GB_end_transaction(gb_main, error);
750            }
751            ASSERT_NO_ERROR(GB_request_undo_type(gb_main, prev_undo_type));
752        }
753
754#if defined(SAVE_COMPRESSION_TREE_TO_DB)
755        error = "fake error";
756#endif // SAVE_COMPRESSION_TREE_TO_DB
757    }
758    return error;
759}
760
761#ifdef DEBUG
762
763void GBT_compression_test(void */*dummy_AW_root*/, GBDATA *gb_main) {
764    GB_ERROR  error     = GB_begin_transaction(gb_main);
765    char     *ali_name  = GBT_get_default_alignment(gb_main);
766    char     *tree_name = GBT_read_string(gb_main, "focus/tree_name");
767
768    // GBUSE(dummy);
769    if (!ali_name || !tree_name) error = GB_await_error();
770
771    error = GB_end_transaction(gb_main, error);
772
773    if (!error) {
774        printf("Recompression data in alignment '%s' using tree '%s'\n", ali_name, tree_name);
775        error = GBT_compress_sequence_tree2(gb_main, tree_name, ali_name);
776    }
777
778    if (error) GB_warning(error);
779    free(tree_name);
780    free(ali_name);
781}
782
783#endif
784
785// ******************** Decompress Sequences ********************
786
787static char *g_b_uncompress_single_sequence_by_master(const char *s, const char *master, long size, long *new_size) {
788    const signed char *source = (signed char *)s;
789    char              *dest;
790    const char        *m      = master;
791    unsigned int       c;
792    int                j;
793    int                i;
794    char              *buffer;
795
796    dest = buffer = GB_give_other_buffer((char *)source, size);
797
798    for (i=size; i;) {
799        j = *(source++);
800        if (j>0) {                                  // uncompressed data block
801            if (j>i) j=i;
802            i -= j;
803            for (; j; j--) {
804                c = *(source++);
805                if (!c) c = *m;
806                *(dest++) = c;
807                m++;
808            }
809        }
810        else {                                      // equal bytes compressed
811            if (!j) break;                          // end symbol
812            if (j == -122) {
813                j = *(source++) & 0xff;
814                j |= ((*(source++)) << 8) &0xff00;
815                j = -j;
816            }
817            c = *(source++);
818            i += j;
819            if (i<0) {
820                GB_internal_error("Internal Error: Missing end in data");
821                j += -i;
822                i = 0;
823            }
824            if (c==0) {
825                memcpy(dest, m, -j);
826                dest += -j;
827                m += -j;
828            }
829            else {
830                memset(dest, c, -j);
831                dest += -j;
832                m += -j;
833            }
834        }
835    }
836    *(dest++) = 0;              // NULL of NULL terminated string
837
838    *new_size = dest-buffer;
839    gb_assert(size == *new_size); // buffer overflow
840
841    return buffer;
842}
843
844char *gb_uncompress_by_sequence(GBDATA *gbd, const char *ss, long size, GB_ERROR *error, long *new_size) {
845    char *dest = 0;
846
847    *error = 0;
848    if (!GB_FATHER(gbd)) {
849        *error = "Cannot uncompress this sequence: Sequence has no father";
850    }
851    else {
852        GB_MAIN_TYPE *Main    = GB_MAIN(gbd);
853        GBDATA       *gb_main = (GBDATA*)Main->data;
854        char         *to_free = GB_check_out_buffer(ss); // Remove 'ss' from memory management, otherwise load_single_key_data() may destroy it
855        int           index;
856        GBQUARK       quark;
857
858        {
859            const unsigned char *s = (const unsigned char *)ss;
860
861            index = g_b_read_number2(&s);
862            quark = g_b_read_number2(&s);
863
864            ss = (const char *)s;
865        }
866
867        if (!Main->keys[quark].gb_master_ali) {
868            gb_load_single_key_data(gb_main, quark);
869        }
870
871        if (!Main->keys[quark].gb_master_ali) {
872            *error = "Cannot uncompress this sequence: Cannot find a master sequence";
873        }
874        else {
875            GBDATA *gb_master = gb_find_by_nr(Main->keys[quark].gb_master_ali, index);
876            if (gb_master) {
877                const char *master = GB_read_char_pntr(gb_master); // make sure that this is not a buffer !!!
878
879                gb_assert((GB_read_string_count(gb_master)+1) == size); // size mismatch between master and slave
880                dest = g_b_uncompress_single_sequence_by_master(ss, master, size, new_size);
881            }
882            else {
883                *error = GB_await_error();
884            }
885        }
886        free(to_free);
887    }
888
889    return dest;
890}
Note: See TracBrowser for help on using the browser.