source: tags/initial/TRS/tree_lib.cxx

Last change on this file was 2, checked in by oldcode, 23 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.5 KB
Line 
1/*
2#######################################
3#                                     #
4#    ORS_CLIENT:  JAVA                #
5#    communication with java applet   #
6#                                     #
7####################################### */
8const int MAXIMUM_LINE_LENGTH = 1024;
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <memory.h>
13#include <malloc.h>
14#include <stdarg.h>
15#include <sys/stat.h>
16#include <sys/mman.h>
17#include <arbdb.h>
18char *TRS_map_file(const char *path,int writeable);
19#define GB_map_file TRS_map_file
20#       include <cat_tree.hxx>
21#undef GB_map_file
22#include "tree_lib.hxx"
23#include "trs_proto.h"
24
25FILE *t2j_out;  // output file
26CAT_tree *cat_tree = NULL;      // the tree
27FILE *t2j_debug;
28
29/********************************************************************************************
30                                        error handling
31********************************************************************************************/
32
33char *TRS_error_buffer = 0;
34
35char *TRS_export_error(const char *templat, ...)
36{
37    char buffer[10000];
38    char *p = buffer;
39    va_list     parg;
40    sprintf (buffer,"ARB ERROR: ");
41    p += strlen(p);
42    va_start(parg,templat);     
43
44    vsprintf(p,templat,parg);
45
46    if (TRS_error_buffer) free(TRS_error_buffer);
47    TRS_error_buffer = strdup(buffer);
48    return TRS_error_buffer;
49}
50
51char *TRS_get_error()
52{
53    return TRS_error_buffer;
54}
55
56
57
58
59struct TRS_strstruct {
60    char *TRS_strcat_data;
61    long TRS_strcat_data_size;
62    long TRS_strcat_pos;
63};
64
65void *TRS_stropen(long init_size)       {               /* opens a memory file */
66    struct TRS_strstruct *strstr;
67    strstr = (struct TRS_strstruct *)malloc(sizeof(struct TRS_strstruct));
68    strstr->TRS_strcat_data_size = init_size;
69    strstr->TRS_strcat_pos = 0;
70    strstr->TRS_strcat_data = (char *)malloc((size_t)strstr->TRS_strcat_data_size);
71    strstr->TRS_strcat_data[0] = 0;
72    return (void *)strstr;
73}
74
75char *TRS_strclose(void *strstruct, int optimize)       /* returns the memory file */
76    /* if optimize == 1 then dont waste memory
77                                if optimize == 0 than fast */
78{
79    char *str;
80    struct TRS_strstruct *strstr = (struct TRS_strstruct *)strstruct;
81    if (optimize) {
82        str = strdup(strstr->TRS_strcat_data);
83        free(strstr->TRS_strcat_data);
84    }else{
85        str = strstr->TRS_strcat_data;
86    }
87    free((char *)strstr);
88    return str;
89}
90
91void TRS_strcat(void *strstruct,const char *ptr)        /* this function adds many strings.
92                                                           first create a strstruct with TRS_open */
93{
94    long        len;
95    struct TRS_strstruct *strstr = (struct TRS_strstruct *)strstruct;
96
97    len = strlen(ptr);
98    if (strstr->TRS_strcat_pos + len + 2 >= strstr->TRS_strcat_data_size) {
99        strstr->TRS_strcat_data_size = (strstr->TRS_strcat_pos+len+2)*3/2;
100        strstr->TRS_strcat_data = (char *)realloc((char *)strstr->TRS_strcat_data,(size_t)strstr->TRS_strcat_data_size);
101    }
102    memcpy(strstr->TRS_strcat_data+strstr->TRS_strcat_pos,ptr,(int)len);
103    strstr->TRS_strcat_pos += len;
104    strstr->TRS_strcat_data[strstr->TRS_strcat_pos] = 0;
105}
106
107void TRS_chrcat(void *strstruct,char ch)        /* this function adds many strings.
108                                                   The first call should be a null pointer */
109{
110    struct TRS_strstruct *strstr = (struct TRS_strstruct *)strstruct;
111    if (strstr->TRS_strcat_pos + 3 >= strstr->TRS_strcat_data_size) {
112        strstr->TRS_strcat_data_size = (strstr->TRS_strcat_pos+3)*3/2;
113        strstr->TRS_strcat_data = (char *)realloc((char *)strstr->TRS_strcat_data,
114                                                  (size_t)strstr->TRS_strcat_data_size);
115    }
116    strstr->TRS_strcat_data[strstr->TRS_strcat_pos++] = ch;
117    strstr->TRS_strcat_data[strstr->TRS_strcat_pos] = 0;
118}
119
120
121char *TRS_mergesort(void **array,long start, long end, long (*compare)(void *,void *,char *cd), char *client_data)
122{
123    long size;
124    long mid;
125    long i, j;
126    long        dest;
127    void **buffer;
128    void *ibuf[256];
129    char *error;
130
131    size = end - start;
132    if (size <= 1) {
133        return 0;
134    }
135    mid = (start+end) / 2;
136    error = TRS_mergesort(array,start,mid,compare,client_data);
137    error = TRS_mergesort(array,mid,end,compare,client_data);
138    if (size <256) {
139        buffer = ibuf;
140    }else{
141        buffer = (void **)malloc((size_t)(size * sizeof(void *)));
142    }
143
144    for ( dest = 0, i = start, j = mid ;
145          i< mid && j < end;){
146        if (compare(array[i],array[j],client_data) < 0) {
147            buffer[dest++] = array[i++];
148        }else{
149            buffer[dest++] = array[j++];
150        }
151    }
152    while(i<mid)        buffer[dest++] = array[i++];
153    while(j<end)        buffer[dest++] = array[j++];
154    memcpy( (char *)(array+start),buffer,(int)size * sizeof(void *));
155    if (size>=256) free((char *)buffer);
156    return error;
157}
158/********************************************************************************************
159                                        read a file to memory
160********************************************************************************************/
161char *TRS_read_file(const char *path) 
162{
163    FILE *input;
164    long data_size;
165    char *buffer = 0;
166
167    if (!strcmp(path,"-")) {
168        /* stdin; */
169        int c;
170        void *str = TRS_stropen(1000);
171        c = getc(stdin);
172        while (c!= EOF) {
173            TRS_chrcat(str,c);
174            c = getc(stdin);
175        }
176        return TRS_strclose(str,0);
177    }
178
179    if ((input = fopen(path, "r")) == NULL) {
180        TRS_export_error("File %s not found",path);
181        return NULL;
182    }else{
183        data_size = TRS_size_of_file(path);
184        buffer =  (char *)malloc((size_t)(data_size+1));
185        data_size = fread(buffer,1,(size_t)data_size,input);
186        buffer[data_size] = 0;
187        fclose(input);
188    }
189    return buffer;
190}
191
192char *TRS_map_FILE(FILE *in,int writeable){
193    int fi = fileno(in);
194    long size = TRS_size_of_FILE(in);
195    char *buffer;
196    if (size<=0) {
197        TRS_export_error("TRS_map_file: sorry file not found");
198        return 0;
199    }
200    if (writeable){
201        buffer = (char *)mmap(0, (int)size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fi, 0);/*@@@*/
202    }else{
203        buffer = (char *)mmap(0, (int)size, PROT_READ, MAP_SHARED, fi, 0);/* @@@ */
204    }
205    if (!buffer){
206        TRS_export_error("TRS_map_file: Error Out of Memory: mmap failes ");
207        return 0;
208    }
209    return buffer;
210}
211
212char *TRS_map_file(const char *path,int writeable){
213    FILE *in;
214    char *buffer;
215    in = fopen(path,"r");
216    if (!in) {
217        TRS_export_error("TRS_map_file: sorry file '%s' not readable",path);
218        return 0;
219    }
220    buffer = TRS_map_FILE(in,writeable);
221    fclose(in);
222    return buffer;
223}
224long TRS_size_of_file(const char *path)
225{
226    struct stat gb_global_stt;
227    if (stat(path, &gb_global_stt)) return -1;
228    return gb_global_stt.st_size;
229}
230
231long TRS_size_of_FILE(FILE *in){
232    int fi = fileno(in);
233    struct stat st;
234    if (fstat(fi, &st)) {
235        TRS_export_error("TRS_size_of_FILE: sorry file '%s' not readable");
236        return -1;
237    }
238    return st.st_size;
239}
240
241
242T2J_transfer_struct::T2J_transfer_struct(long size, enum CAT_FIELDS key_indexi) {
243    memset((char *)this,0,sizeof(T2J_transfer_struct));
244    nitems = size;
245    items = (T2J_item *)calloc(sizeof(T2J_item),(int)size);
246    this->key_index = key_indexi;
247}
248
249/***********************************************************************
250                To output stream: nibbles bytes and integers
251***********************************************************************/
252int t2j_last_nibble  = -1;
253
254GB_INLINE void t2j_write_nibble(int value){
255    if (t2j_last_nibble<0) {
256        t2j_last_nibble = value;
257    }else{
258        int o = t2j_last_nibble<<4 | value;
259        fputc(o,t2j_out);
260        t2j_last_nibble = -1;
261    }
262}
263
264GB_INLINE void t2j_flush_nibble(void){
265    if (t2j_last_nibble>=0) {
266        int o = t2j_last_nibble<<4 | 15;
267        fputc(o,t2j_out);
268        t2j_last_nibble = -1;
269    }   
270}
271
272int t2j_last_bit_string = 0;
273int t2j_bits_already_in_c = 0;
274
275GB_INLINE void t2j_flush_bits(void){
276    fputc(t2j_last_bit_string,t2j_out);
277    t2j_last_bit_string = 0;
278    t2j_bits_already_in_c = 0;
279}
280
281GB_INLINE void t2j_write_bit(int bit){
282    if (bit) {
283        t2j_last_bit_string |=  0x80 >> t2j_bits_already_in_c;
284    }
285    if ((++t2j_bits_already_in_c) >=8) {
286        t2j_flush_bits();
287    }
288}
289
290
291void t2j_write_byte(int value){
292    t2j_flush_nibble();
293    fputc(value,t2j_out);
294}
295
296char *t2j_write_int2(unsigned int value){
297    register int i;
298    i = (value >>24) & 0xff; t2j_write_byte(i);
299    i = (value >>16) & 0xff; t2j_write_byte(i);
300    i = (value >>8) & 0xff; t2j_write_byte(i);
301    i = (value >>0) & 0xff; t2j_write_byte(i);
302    return 0;
303}
304
305char *t2j_write_uint(unsigned int value, int or_cmd){
306    t2j_write_nibble(0);                // attention
307    register int i;
308    if (value >= 0x1000000) {
309        t2j_write_nibble(4 | or_cmd);           // how many bytes !!!!
310        i = (value >>24) & 0xff; t2j_write_byte(i);
311        i = (value >>16) & 0xff; t2j_write_byte(i);
312        i = (value >>8) & 0xff; t2j_write_byte(i);
313        i = (value >>0) & 0xff; t2j_write_byte(i);
314    }else if (value >= 0x1000) {
315        t2j_write_nibble(3 | or_cmd);
316        i = (value >>16) & 0xff; t2j_write_byte(i);
317        i = (value >>8) & 0xff; t2j_write_byte(i);
318        i = (value >>0) & 0xff; t2j_write_byte(i);
319    }else if (value >= 0x100){
320        t2j_write_nibble(2 | or_cmd);
321        i = (value >>8) & 0xff; t2j_write_byte(i);
322        i = (value >>0) & 0xff; t2j_write_byte(i);
323    }else{
324        t2j_write_nibble(1 | or_cmd);
325        i = (value >>0) & 0xff; t2j_write_byte(i);
326    }
327    return 0;
328}
329
330/***********************************************************************
331        Sends the data in nodes->user_data to the java programm
332        Sideeffects:    writes to t2j_out
333                        uses cat_tree
334***********************************************************************/
335
336struct t2j_s1_item {
337    CAT_node_id id;
338    struct t2j_s1_item *next;
339};
340
341struct t2j_s1_item_header {
342    struct t2j_s1_item *first;
343    struct t2j_s1_item *last;
344    char        *value;
345    long        focus_members;
346    long        members;
347    long        estimated_transfer_size;                // very rough idea !!!
348};
349
350CAT_node_id t2j_get_focus_right_bound(CAT_node_id focus){
351    while (cat_tree->nodes[focus].rightson) {
352        focus = cat_tree->nodes[focus].rightson;
353    }
354    return focus;
355}
356
357/***********************************************************************
358        Compare Function to sort the result list,
359        The idea is that data within the focus is transferred first,
360        followed by data with a lot of hits
361        Sideeffects: sorts an void ** array
362***********************************************************************/
363long t2j_compare_two_hitems(struct t2j_s1_item_header *hi0, struct t2j_s1_item_header *hi1){
364    double l = (hi0->focus_members + hi0->members/20) / hi0->estimated_transfer_size;
365    double r = (hi1->focus_members + hi1->members/20) / hi1->estimated_transfer_size;
366    if (l>r) return 1;
367    return -1;
368}
369
370long t2j_compare_two_ids(long i1, long i2) {
371    if (i1 < i2) return -1;
372    return 1;
373}
374
375void t2j_write_range(int start_of_range, int end_of_range){
376    int rsize = end_of_range - start_of_range;
377    if (rsize == 1) {           // no range !!!
378        t2j_write_nibble(rsize);
379    }else{
380        if (rsize >= 15) {
381            t2j_write_uint(rsize,8);
382        }else{
383            t2j_write_nibble(15);
384            t2j_write_nibble(rsize);
385        }
386    }
387}
388
389void t2j_indexlist_2_OTF(long *buffer, long buf_size){
390    int j;
391    int start_of_range, end_of_range;
392    start_of_range = end_of_range = -1;
393
394    TRS_mergesort((void **)buffer,0,buf_size,
395                  (long (* )(void *, void *, char *cd ))t2j_compare_two_ids,0);
396
397    for (j = 0; j < buf_size; j++) {
398        int id = (int) buffer[j];
399        if (id == end_of_range + 1){            // resize range
400            end_of_range++;
401        }else{
402            // write out range !!!
403            if (end_of_range > start_of_range){
404                t2j_write_range(start_of_range,end_of_range);
405            }
406            int rsize = (int)id - end_of_range;
407            if (rsize >= 15) {
408                t2j_write_uint(rsize,0);
409            }else{
410                t2j_write_nibble(rsize);
411            }
412            start_of_range = end_of_range = (int)id;
413        }
414    }
415    if (end_of_range > start_of_range){         // last range
416        t2j_write_range(start_of_range,end_of_range);
417    }
418
419    t2j_write_nibble(0);
420    t2j_write_nibble(0);
421    t2j_flush_nibble();                 // back to byte boundary !!!
422}
423
424/***********************************************************************
425        Send all information stored in cat_tree->nodes[xx].user_data
426***********************************************************************/
427char *T2J_send_tree(CAT_node_id focus){
428    struct t2j_s1_item_header **hitems =
429        (struct t2j_s1_item_header **)calloc(sizeof(struct t2j_s1_item_header *),
430                                             (int)cat_tree->nnodes);    // nnodes is the very worst case !!!
431    if (focus <0 || focus >= cat_tree->nnodes) focus = 0;
432    int header_in_use = 0;
433    CAT_node_id left_focus = focus;
434    CAT_node_id right_focus = t2j_get_focus_right_bound(focus);
435    long        convert_hash = TRS_create_hash(cat_tree->nnodes);
436    CAT_node_id i;
437
438    // ********* collect the answer in a hash table
439    for (i=0; i<cat_tree->nnodes; i++){
440        CAT_node *node = & cat_tree->nodes[i];
441        char *s = node->user_data;
442        if (!s) continue;
443        struct t2j_s1_item *item = (struct t2j_s1_item *)
444            calloc(sizeof(struct t2j_s1_item),1);
445        item->id = i;
446        struct t2j_s1_item_header *hitem =
447            (struct t2j_s1_item_header *)TRS_read_hash(convert_hash, s);
448        if (!hitem) {
449            hitem = (struct t2j_s1_item_header *)
450                calloc(sizeof(struct t2j_s1_item_header),1);
451            hitems[header_in_use++] = hitem;
452            hitem ->first = hitem->last = item;
453            hitem->estimated_transfer_size = strlen(s)+5;
454            hitem->value = s;
455            TRS_write_hash_no_strdup(convert_hash,s,(long)hitem);
456        }else{
457            if (hitem->last->id != i-1) {
458                hitem->estimated_transfer_size += 1;
459            }
460            hitem->last->next = item;
461            hitem->last = item;
462        }
463        hitem->members++;
464        if (i >= left_focus && i <= right_focus) hitem->focus_members++;
465    }
466    // ***** sort it by quality
467    TRS_mergesort((void **)hitems,0,header_in_use,      (long (* )(void *, void *, char *cd ))t2j_compare_two_hitems,0);
468
469    CAT_NUMBERING numbering = CAT_NUMBERING_LEVELS;
470    fputc(T2J_LEVEL_INDEXING,t2j_out);  // Write OTF tag
471    t2j_write_int2(header_in_use);              // number of items
472
473
474    for (i = 0; i< header_in_use; i++) {        // go through all values
475        struct t2j_s1_item_header *hitem = hitems[i];
476        int     redo_needed;
477        struct t2j_s1_item *item;
478        long *buffer = (long *)calloc(sizeof(long) , (int)hitem->members);
479        char color_tab[256];                            // already sent color info
480        int j;
481        for (j=0;j<256;j++) color_tab[j] = 0;           // nothing has been sent yet
482        struct t2j_s1_item *ref_item;
483        for (ref_item = hitem->first; ref_item; ref_item = ref_item->next) {
484            CAT_node *node = & cat_tree->nodes[ref_item->id];
485            int color = node->color;
486            int grouped = node->is_grouped;
487            int col_ref = grouped | (color<<4);
488            if (color_tab[col_ref]) continue;           // has already been sent
489            color_tab[col_ref] = 1;                             // is to be sent
490            t2j_write_byte(col_ref);
491            redo_needed = 0;
492            fwrite(hitem->value, strlen(hitem->value)+1, 1, t2j_out);
493
494            for (j=0, item = ref_item; item; item = item->next) {
495                CAT_node *nod = & cat_tree->nodes[item->id];
496                if (nod->is_grouped != grouped || nod->color != color) {
497                    redo_needed = 1;
498                    continue;
499                }
500                buffer[j++] = cat_tree->nodes[item->id].numbering[numbering];
501            }
502            t2j_indexlist_2_OTF(buffer,j );
503            if (!redo_needed) break;
504        }
505
506        delete buffer;
507
508    }
509    return 0;
510}
511
512/***********************************************************************
513        Transform any query list
514        mode = 1 to OTF
515        mode = 0 to SelectionString
516        Sideeffects: no !!!!
517***********************************************************************/
518char *T2J_transform(int mode, char *path_of_tree, struct T2J_transfer_struct *data, CAT_node_id focus, FILE *out){
519    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);
520    if (!cat_tree) return TRS_get_error();
521    t2j_out = out;
522    long index = TRS_create_hash(cat_tree->nnodes);
523    int i;
524    // create the index !!!!!!!!!!!!
525    for (i=0;i< cat_tree->nnodes;i++) {
526        if (cat_tree->nodes[i].field_offsets[data->key_index]) {
527            TRS_write_hash_no_strdup(index,cat_tree->data +     cat_tree->nodes[i].field_offsets[data->key_index],i+1);
528        }else   if (cat_tree->nodes[i].field_offsets[CAT_FIELD_GROUP_NAME]) {
529            TRS_write_hash_no_strdup(index,cat_tree->data +     cat_tree->nodes[i].field_offsets[CAT_FIELD_GROUP_NAME],i+1);
530        }
531    }
532
533
534    for (i=0;i<data->nitems;i++) {
535        long ind = TRS_read_hash(index, data->items[i].key);
536        if (!ind) continue;
537        ind -= 1;
538        cat_tree->nodes[ind].color = data->items[i].color;
539        cat_tree->nodes[ind].user_data = data->items[i].value;
540    }
541    if (mode == 1) {
542        return T2J_send_tree(focus);
543    }else{
544        T2J_convert_colors_into_selection();
545        return 0;
546    }
547}
548
549
550/***********************************************************************
551        Send the tree.   A '1' bit indicates a node '0' a leaf
552        Sideeffects: writes to out
553***********************************************************************/
554char *T2J_send_bit_coded_tree(char *path_of_tree, FILE *out){
555    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree); // 3 lines that should never be deleted
556    if (!cat_tree) return TRS_get_error();
557    t2j_out = out;
558
559    int i;
560    t2j_write_uint(cat_tree->nnodes,0);
561    for (i=0;i<cat_tree->nnodes;i++){
562        CAT_node *node = & cat_tree->nodes[i];
563        if (node->leftson) {
564            t2j_write_bit(1);
565        }else{
566            t2j_write_bit(0);
567        }
568    }
569    t2j_flush_bits();
570    return 0;
571}
572/***********************************************************************
573        Send the tree.   level numbering !!! branch lengths from 0-15
574        Sideeffects: writes to out
575***********************************************************************/
576CAT_node_id *t2j_mcreate_level_indexing(void){
577    static CAT_node_id *ids = NULL;
578    if (ids) return ids;
579    ids = (CAT_node_id *)calloc(sizeof(CAT_node_id), cat_tree->nnodes);
580    int i;
581    for (i=0;i< cat_tree->nnodes;i++) {
582        ids[cat_tree->nodes[i].numbering[CAT_NUMBERING_LEVELS]] = i;
583    }
584    return ids;
585}
586
587char *T2J_send_branch_lengths(char *path_of_tree, FILE *out){
588    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);         // 3 lines that should never be deleted
589    if (!cat_tree) return TRS_get_error();
590    t2j_out = out;
591    CAT_node_id *ids = t2j_mcreate_level_indexing();
592    int i;
593    for (i=0;i<cat_tree->nnodes;i++){
594        CAT_node *node = & cat_tree->nodes[ids[i]];
595        int bl = node->branch_length_byte;
596        if (bl>=16) bl = 15;
597        t2j_write_nibble(bl);
598    }
599    delete ids;
600    t2j_flush_nibble();
601    return 0;
602}
603/***********************************************************************
604        Send tree in newick format
605        File Syntax: id#value\nid#value\n....
606        if node is grouped -> subtree is not exported
607        if node.color == 0 -> prune node
608        add addbl to branch length
609       
610***********************************************************************/
611#define SEPERATOR '\''
612
613void t2j_send_newick_rek(CAT_node *node, double addbl, FILE *out){
614    const char *name = 0;
615
616    if (!node->leftson){        // leaf
617        {
618            int n_offset = node->field_offsets[CAT_FIELD_NAME];
619            if (n_offset){
620                name = & cat_tree->data[n_offset];
621                const char *full_name = "";
622                int fn_offset = node->field_offsets[CAT_FIELD_FULL_NAME];
623                if (fn_offset){
624                    full_name = &cat_tree->data[fn_offset];
625                }
626                fprintf(out,"'%s#%s':%f",name,full_name,node->branch_length_float + addbl);
627            }
628        }
629        return;
630    }
631    {
632        int n_offset = node->field_offsets[CAT_FIELD_GROUP_NAME];
633        if (n_offset){
634            name = & cat_tree->data[n_offset];
635        }
636    }
637   
638    CAT_node *ln = &cat_tree->nodes[node->leftson];
639    CAT_node *rn = &cat_tree->nodes[node->rightson];
640   
641    if ( (ln->color & rn->color ) == 0){        // prune tree, descend into only one branch
642        if (ln->color != 0){
643            t2j_send_newick_rek(ln,addbl + node->branch_length_float ,out);
644        }else{
645            t2j_send_newick_rek(rn,addbl + node->branch_length_float ,out);
646        }
647        return;
648    }
649   
650    if (!node->is_grouped){
651        fprintf(out,"(");
652        t2j_send_newick_rek(ln,0,out);
653        fprintf(out,",");
654        t2j_send_newick_rek(rn,0,out);
655        fprintf(out,")");
656    }else{
657        fprintf(out,"[GROUPED=%li]",node->nleafs);
658    }
659    if (name){
660        fprintf(out,"'%s':%f\n",name,addbl + node->branch_length_float);
661    }else{
662        fprintf(out,":%f\n",addbl + node->branch_length_float);
663    }
664}
665
666GB_ERROR t2j_patch_tree(CAT_node_id *levelindex,char *patch){
667    int c;
668    char *readp = strdup(patch);
669    c = *(readp++);
670    while (c != 0){
671        int fac = 1;
672        int s = 0;
673        while ( c >='A' && c <='Z' ) {          // Read the start of the selection
674            s += fac * (c-'A');
675            fac *= 16;
676            c = *(readp++);
677        }
678        if (s<0 || s > cat_tree->nnodes){
679            return TRS_export_error("Node out of bound %i",s);
680        }
681        CAT_node *node = &cat_tree->nodes[levelindex[s]];
682        if (c != SEPERATOR){
683            return TRS_export_error("Unknown character in patch '%c' '%c' expected in :'%s'",c,SEPERATOR,patch);
684        }
685        char *nread;
686        nread = strchr(readp,SEPERATOR);
687        if (!nread){
688            return TRS_export_error("Missing second '%c' int '%s'",SEPERATOR,patch);
689        }
690
691        *nread = 0;
692        {                       // patch node
693            char *new_name = strdup(readp);
694            if (node->leftson){ // internal group
695                node->field_offsets[CAT_FIELD_GROUP_NAME] = new_name - &cat_tree->data[0];
696            }else{
697                node->field_offsets[CAT_FIELD_FULL_NAME] = new_name - &cat_tree->data[0];
698            }
699        }
700        readp = nread+1;
701        c = *(readp++);
702    }
703    return 0;
704}
705
706const char *t2j_group_tree(CAT_node_id *levelindex,const char *grouped){
707    int c;
708    const char *readp = grouped;
709    c = *(readp++);
710    while (c != 0){
711        int fac = 1;
712        int s = 0;
713        while ( c >='A' && c <='Z' ) {          // Read the start of the selection
714            s += fac * (c-'A');
715            fac *= 16;
716            c = *(readp++);
717        }
718        if (s<0 || s >= cat_tree->nnodes){
719            return TRS_export_error("Node out of bound %i",s);
720        }
721        CAT_node *node = &cat_tree->nodes[levelindex[s]];
722        if (c != '_'){
723            if (c){
724                return TRS_export_error("Unknown character in groupstring '%c' '_' expected",c);
725            }else{
726                readp--;
727            }
728        }
729        node->is_grouped = 1;
730        c = *(readp++);
731    }
732    return 0;
733}
734
735           
736char *T2J_send_newick_tree(const char *path_of_tree,
737                           char *changedNodes,
738                           char *selectedNodes,
739                           const char *grouped_nodes,
740                           FILE *out){
741    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree); // 3 lines that should never be deleted
742    if (!cat_tree) return TRS_get_error();
743    t2j_out = out;
744    CAT_node_id *levelindex = t2j_mcreate_level_indexing();
745    if (changedNodes && strlen(changedNodes)){
746        const char *error = t2j_patch_tree(levelindex,changedNodes);
747        if (error) {
748            fprintf(out,"%s\n",error);
749            return 0;
750        }
751    }
752   
753    T2J_set_color_of_selection(selectedNodes);
754   
755    {
756        int i;
757        for (i=0;i<cat_tree->nnodes;i++){
758            cat_tree->nodes[i].is_grouped = 0;
759        }
760        if (grouped_nodes && strlen(grouped_nodes)){
761            t2j_group_tree(levelindex,grouped_nodes);
762        }
763    }
764    fprintf(out,"[%i]\n",cat_tree->nnodes);
765    t2j_send_newick_rek(&cat_tree->nodes[0],0.0,out);
766    fprintf(out,"\n");
767    return 0;
768}
769
770/***********************************************************************
771        Read a file into the transfer struct:
772        File Syntax: id#value\nid#value\n....
773***********************************************************************/
774struct T2J_transfer_struct *T2J_read_query_result_from_data(char *data,CAT_FIELDS catfield){
775    int nls = 0;
776    char *p;
777    for (p = data; p ; p = strchr(p+1,'\n')) nls++;
778    T2J_transfer_struct *transfer = new T2J_transfer_struct(nls,catfield);
779    nls = 0;
780    char *np;
781    char ascii_2_col[256];
782    memset(ascii_2_col,T2J_COLOR_UNKNOWN,256);
783    ascii_2_col['+'] = T2J_COLOR_YES;
784    ascii_2_col['p'] = T2J_COLOR_YES;
785    ascii_2_col['1'] = T2J_COLOR_YES;
786    ascii_2_col['-'] = T2J_COLOR_NO;
787    ascii_2_col['n'] = T2J_COLOR_NO;
788    ascii_2_col['0'] = T2J_COLOR_NO;
789    int i;
790    for (i=0;i<10;i++) {
791        ascii_2_col['0' + i] = i;
792    }
793    for (i=0;i<6;i++){
794        ascii_2_col['a' + i] = i + 10;
795        ascii_2_col['A' + i] = i + 10;
796    }
797    for (p = data; p ; p = np) {
798        np = strchr(p,'\n');
799        if (np) *(np++) = 0;
800
801        char *col = strchr(p,'#');      // color
802        if (!col) continue;
803        *(col++) = 0;
804
805        char *val = strchr(col,'#');    // value
806        if (!val) continue;
807        *(val++) = 0;
808        while ( *p == ' ') p++;         // remove leading spaces
809        while ( *val == ' ') val++;
810        transfer->items[nls].key = p;
811        transfer->items[nls].color = ascii_2_col[col[0]];
812        if (np - val > MAXIMUM_LINE_LENGTH) val[MAXIMUM_LINE_LENGTH] = 0;// maximum line length 1000
813        transfer->items[nls].value = val;
814        nls++;
815    }
816    transfer->nitems = nls;
817    return transfer;
818}
819/***********************************************************************
820        Read a string from pt_server into the transfer struct:
821        File Syntax: dummy\1id\1value\1id\1value...\0
822***********************************************************************/
823struct T2J_transfer_struct *T2J_read_query_result_from_pts(char *data){
824    int nls = 0;
825    char *p;
826    for (p = data; p ; p = strchr(p+1,1)) nls++;
827    T2J_transfer_struct *transfer = new T2J_transfer_struct(nls/2+1,CAT_FIELD_NAME);
828    nls = 0;
829    char *start = strchr(data,1);
830    if(!start) {
831        TRS_export_error("No hits");
832        return 0;
833    }
834    char *next;
835    for ( start++; start; start=next ) {
836        char *info = strchr(start,1);
837        if (!info) break;
838        *info=0;
839        info++;
840        next = strchr(info,1);
841        if (next) *(next++) = 0;
842        transfer->items[nls].key = start;
843        transfer->items[nls].color = T2J_COLOR_YES;
844        transfer->items[nls].value = info;
845        nls++;
846    }
847    transfer->nitems = nls;
848    return transfer;
849}
850/***********************************************************************
851        Read a file into the transfer struct:
852        File Syntax: id#value\nid#value\n....
853***********************************************************************/
854struct T2J_transfer_struct *T2J_read_query_result_from_file(char *path,CAT_FIELDS catfield){
855    char *data = TRS_read_file(path);
856    if (!data) {
857        TRS_export_error("Cannot open datafile '%s'",path);
858        return 0;
859    }
860    return T2J_read_query_result_from_data(data,catfield);
861}
862/***********************************************************************
863        Transfer the first word of the full_name ...
864***********************************************************************/
865char *T2J_transfer_fullnames1(char *path_of_tree,FILE *out) {
866    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);         // 3 lines that should never be deleted
867    if (!cat_tree) return TRS_get_error();
868    t2j_out = out;
869
870    int i;
871    for (i=0;i<cat_tree->nnodes;i++){
872        CAT_node *node = & cat_tree->nodes[i];
873        if (node->field_offsets[CAT_FIELD_FULL_NAME]) {
874            node->user_data = cat_tree->data + node->field_offsets[CAT_FIELD_FULL_NAME];
875            char *sep = strchr(node->user_data,' ');
876            if (sep) *sep = 0;
877        }
878        node->color = (node->color_in + 14 - T2J_COLOR_YES) & 15;
879    }
880    return T2J_send_tree(0);
881}
882
883
884/***********************************************************************
885        Transfer the rest word of the full_name ...
886***********************************************************************/
887char *T2J_transfer_fullnames2(char *path_of_tree,FILE *out) {
888    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);         // 3 lines that should never be deleted
889    if (!cat_tree) return TRS_get_error();
890    t2j_out = out;
891
892    int i;
893    for (i=0;i<cat_tree->nnodes;i++){
894        CAT_node *node = & cat_tree->nodes[i];
895        if (node->field_offsets[CAT_FIELD_FULL_NAME]) {
896            node->user_data = cat_tree->data + node->field_offsets[CAT_FIELD_FULL_NAME];
897            char *sep = strchr(node->user_data,' ');
898            if (sep){
899                while (*sep == ' ') sep++;
900            }
901            node->user_data = sep;
902        }
903        node->color = 0;
904    }
905    return T2J_send_tree(0);
906}
907
908/***********************************************************************
909        Transfer inner node labels ...
910***********************************************************************/
911char *T2J_transfer_group_names(char *path_of_tree,FILE *out) {
912    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);         // 3 lines that should never be deleted
913    if (!cat_tree) return TRS_get_error();
914    t2j_out = out;
915
916    int i;
917    for (i=0;i<cat_tree->nnodes;i++){
918        CAT_node *node = & cat_tree->nodes[i];
919        if (node->field_offsets[CAT_FIELD_GROUP_NAME]) {
920            node->user_data = cat_tree->data + node->field_offsets[CAT_FIELD_GROUP_NAME];
921        }
922               
923    }
924    return T2J_send_tree(0);
925}
926
927long    t2j_get_deepest_node_that_contains_all_selected(CAT_node_id nn, 
928                                                        char *selected_ids,long nselected, CAT_node_id *focusout){
929    CAT_node *node = & cat_tree->nodes[nn];
930    long sum = 0;
931    if (node->leftson > 0) {            // inner node
932        sum += t2j_get_deepest_node_that_contains_all_selected( node->leftson,
933                                                                selected_ids, nselected, focusout);
934        sum += t2j_get_deepest_node_that_contains_all_selected( node->rightson,
935                                                                selected_ids, nselected, focusout);
936    }else{
937        sum += selected_ids[nn];        // count the selected leafs
938    }
939    if (sum == nselected){                      // there is a hit !!
940        if (*focusout == 0) {           // and it is really the first one
941            *focusout = nn;             // export it
942        }
943    }
944    return sum;
945}
946
947/***********************************************************************
948*       Convert names into selection
949************************************************************************/
950void t2j_out_number( int number, char base){
951    do {
952        printf("%c", (number &0xf) + base);
953        number = number>>4;
954    } while(number != 0);
955}
956
957void T2J_convert_colors_into_selection(){
958    int p = 0;
959    int lastWritten = 0;                // level Numbering
960    while ( p < cat_tree->nnodes ){
961        // search a selected terminal
962        int sel;
963        for (sel = p; sel < cat_tree->nnodes; sel++){
964            if ( cat_tree->nodes[sel].leftson != 0) continue; // inner node
965            if ( cat_tree->nodes[sel].color) break;
966        }
967        if (sel == cat_tree->nnodes) break;     // no more selections
968        // search a non selected terminal
969       
970        int nsel;
971        for (nsel = sel; nsel < cat_tree->nnodes; nsel++){
972            if ( cat_tree->nodes[nsel].leftson != 0) continue; // inner node
973            if ( !cat_tree->nodes[nsel].color) break;
974        }
975        p = nsel;                               // start of next search
976        int first = cat_tree->nodes[sel].numbering[CAT_NUMBERING_LEVELS];               // convert to level numbering
977        int last = nsel;
978        if (nsel < cat_tree->nnodes) last = cat_tree->nodes[nsel].numbering[CAT_NUMBERING_LEVELS];
979       
980        int h = lastWritten;
981        lastWritten = last;
982        last -= first;  // calculate delta values
983        first -= h;
984
985        t2j_out_number( first,'A' );
986        t2j_out_number( last,'a' );     
987    }
988    printf("\n");
989}
990
991
992/***********************************************************************
993        Convert a selection into names ...
994***********************************************************************/
995/**     input path_of_tree      path of the tree.otb file
996        sel                     what is send from the java as a selection
997        varname                 a string that is prepended to the output
998        all_nodes               output = all nodes or just ranges
999        field_name              which field should be placed in the output CAT_FIELD_NAME/CAT_FIELD_FULL_NAME ...
1000
1001        if all_nodes >0 then the programm calculates:
1002        focusout                the internal id that contains all selected nodes
1003        maxnodeout              the name of the inner node that contains all selected nodes
1004        maxnodehits             relativ number of selected_nodes/tip beneath maxnodeout
1005*/
1006
1007char *T2J_get_selection(char *path_of_tree, char *sel, const char *varname, int all_nodes,CAT_FIELDS field_name,
1008                        CAT_node_id *focusout, char **maxnodeout, double *maxnodehits){
1009    if (!cat_tree)      cat_tree = load_CAT_tree(path_of_tree);
1010    if (!cat_tree) return 0;
1011    CAT_node_id *levelindex = t2j_mcreate_level_indexing();
1012       
1013    char *readp = sel;
1014    int nselected = 0;
1015    char *selected_ids = (char *)calloc(sizeof(char), cat_tree->nnodes);
1016    void *memfile = TRS_stropen(1024);
1017    int s,e;
1018    int c;
1019    int fac;
1020    TRS_strcat(memfile,varname);
1021    readp = sel;
1022    c = *(readp++); 
1023    int last = 0;
1024    for (; c >='A' && c <='Z'; ){
1025        fac = 1;s = last;
1026        while ( c >='A' && c <='Z' ) {          // Read the start of the selection
1027            s += fac * (c-'A');
1028            fac *= 16;
1029            c = *(readp++);
1030        }
1031        fac = 1;e = s;
1032        while ( c >='a' && c <='z' ) {          // End of the selection
1033            e += fac * (c-'a');
1034            fac *= 16;
1035            c = *(readp++);
1036        }
1037        if (e<=0) e=1;
1038        if (s<0) s= 0;
1039        if (e > cat_tree->nnodes) e = cat_tree->nnodes;
1040        if (s >= cat_tree->nnodes) e = cat_tree->nnodes-1;
1041        last = e;
1042               
1043        if (all_nodes) {
1044            for (;s<e;s++) {
1045                TRS_strcat(memfile,     cat_tree->data +
1046                           cat_tree->nodes[levelindex[s]].
1047                           field_offsets[field_name]);
1048                nselected++;
1049                selected_ids[levelindex[s]] ++;
1050                TRS_chrcat(memfile,'#');
1051            }
1052        }else{
1053            TRS_strcat(memfile,cat_tree->data + 
1054                       cat_tree->nodes[levelindex[s]].field_offsets[field_name]);
1055            // thats one of my favourite statements
1056            TRS_chrcat(memfile,'#');
1057            TRS_strcat(memfile,cat_tree->data +
1058                       cat_tree->nodes[levelindex[e-1]].field_offsets[field_name]);
1059            TRS_chrcat(memfile,' ');
1060        }
1061    }
1062    char *result = TRS_strclose(memfile,0);
1063    if (focusout) {
1064        *focusout = 0;
1065        if (maxnodeout ) *maxnodeout = 0;
1066        if (maxnodehits) *maxnodehits = 0.0;
1067        if (nselected == 1) {
1068            t2j_get_deepest_node_that_contains_all_selected(
1069                                                            0,selected_ids,nselected,focusout);
1070            if (maxnodeout ) *maxnodeout = cat_tree->data + 
1071                                 cat_tree->nodes[*focusout].
1072                                 field_offsets[CAT_FIELD_NAME];
1073            if (maxnodehits) *maxnodehits = 1.0;
1074        }else if (nselected) {
1075            t2j_get_deepest_node_that_contains_all_selected(
1076                                                            0,selected_ids,nselected,focusout);
1077            CAT_node_id nextuppderlabeldnode = *focusout;
1078
1079            while ( nextuppderlabeldnode > 0 
1080                    && cat_tree->nodes[nextuppderlabeldnode].
1081                    field_offsets[CAT_FIELD_GROUP_NAME] == 0 ) {
1082                nextuppderlabeldnode = cat_tree->nodes[nextuppderlabeldnode].father;
1083            }
1084            if (nextuppderlabeldnode) { // get the name of the node
1085                if (maxnodeout ) *maxnodeout = cat_tree->data + 
1086                                     cat_tree->nodes[nextuppderlabeldnode].
1087                                     field_offsets[CAT_FIELD_GROUP_NAME];
1088                if (maxnodehits) *maxnodehits = (double)nselected/
1089                                     (double) cat_tree->nodes[nextuppderlabeldnode].nleafs;
1090            }
1091        }
1092    }
1093    delete selected_ids;
1094    return result;
1095}
1096
1097/** set color of inner nodes:
1098    color = leftson.color | rightson.color
1099    */
1100
1101int t2j_set_color_rek(int node){
1102    int ls = cat_tree->nodes[node].leftson;
1103    int rs = cat_tree->nodes[node].rightson;
1104    int color = 0;
1105    if (ls != 0) color |= t2j_set_color_rek(ls);
1106    else        color |= cat_tree->nodes[node].color;
1107    if (rs != 0) color |= t2j_set_color_rek(rs);
1108    else        color |= cat_tree->nodes[node].color;
1109    cat_tree->nodes[node].color = color;
1110    return color;
1111}
1112
1113/***********************************************************************
1114        Convert a selection into names ...
1115***********************************************************************/
1116/**     input path_of_tree      path of the tree.otb file
1117        sel                     what is send from the java as a selection
1118        sets the color of all selected nodes to one, others to 0
1119        inner node get one if at least one child is set to one
1120*/
1121
1122void T2J_set_color_of_selection(char *sel ){
1123    if (!sel){
1124        /**   select all nodes */
1125        for (int s=  0; s < cat_tree->nnodes; s++){
1126            cat_tree->nodes[s].color = 1;
1127        }
1128        return;
1129    }
1130    int s,e;
1131    int c;
1132    int fac;
1133    char *readp = sel;
1134    int last = 0;
1135    CAT_node_id *levelindex = t2j_mcreate_level_indexing();
1136
1137    /** deselect all nodes */
1138    for ( s = 0; s < cat_tree->nnodes;s++){
1139        cat_tree->nodes[s].color = 0;
1140    }
1141
1142                 
1143    c = *(readp++); 
1144    for (; c >='A' && c <='Z'; ){
1145        fac = 1;s = last;
1146        while ( c >='A' && c <='Z' ) {          // Read the start of the selection
1147            s += fac * (c-'A');
1148            fac *= 16;
1149            c = *(readp++);
1150        }
1151        fac = 1;e = s;
1152        while ( c >='a' && c <='z' ) {          // End of the selection
1153            e += fac * (c-'a');
1154            fac *= 16;
1155            c = *(readp++);
1156        }
1157        if (e<=0) e=1;
1158        if (s<0) s= 0;
1159        if (e > cat_tree->nnodes) e = cat_tree->nnodes;
1160        if (s >= cat_tree->nnodes) e = cat_tree->nnodes-1;
1161        last = e;
1162               
1163        for (;s<e;s++) {
1164            cat_tree->nodes[levelindex[s]].color = 1;
1165        }
1166    }
1167    t2j_set_color_rek(0);
1168}
1169
Note: See TracBrowser for help on using the repository browser.