root/branches/stable_5.0/DIST/DI_compress_matrix.cxx

Revision 5392, 4.6 KB (checked in by westram, 4 years ago)

- changed prefix 'ph' to 'di'

('ph' is used in ../PHYLO, and many identifiers are duplicated)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <memory.h>
5
6#include <arbdb.h>
7#include <arbdbt.h>
8
9#include <aw_root.hxx>
10#include <aw_device.hxx>
11#include <aw_window.hxx>
12#include <aw_preset.hxx>
13
14#include <awt_tree.hxx>
15#include "dist.hxx"
16
17#include <di_matr.hxx>
18#include <di_view_matrix.hxx>
19
20/*  returns 1 only if groupname != null and there are species for that group */
21int DI_MATRIX::search_group(GBT_TREE *node,GB_HASH *hash, long *groupcnt,char *groupname, DI_ENTRY **groups){
22    if (node->is_leaf) {
23        if (!node->name) return 0;
24        DI_ENTRY *phentry = (DI_ENTRY *)GBS_read_hash(hash,node->name);
25        if (!phentry) {     // Species is not a member of tree
26            return 0;
27        }
28        if (groupname) {        // There is a group for this species
29            phentry->group_nr = *groupcnt;
30            return 1;
31        }
32        return 0;
33    }
34    char *myname;
35    if (groupname) {
36        myname = groupname;
37    }
38    else{
39        myname = 0;
40        if (node->gb_node && node->name){       // but we are a group
41            GBDATA *gb_grouped = GB_entry(node->gb_node, "grouped");
42            if (gb_grouped && GB_read_byte(gb_grouped)) {
43                myname = node->name;
44            }
45        }
46    }
47    int erg = search_group(node->leftson,hash,groupcnt,myname,groups) +
48        search_group(node->rightson,hash,groupcnt,myname,groups);
49
50    if (!groupname){        // we are not a sub group
51        if (myname){        // but we are a group
52            if (erg>0) {            // it is used
53                groups[*groupcnt] = new DI_ENTRY(myname,this);
54                (*groupcnt)++;
55            }
56        }
57        return 0;
58    }
59    else {
60        return erg;         // We are using an inherited group
61    }
62}
63
64char *DI_MATRIX::compress(GBT_TREE *tree){
65    GB_HASH *hash = GBS_create_hash(nentries*2, GB_IGNORE_CASE);
66    int i,j;            // create a hash table of species
67    char *error = 0;
68    for (i=0;i<nentries;i++) {
69        if (entries[i]->name) {
70            GBS_write_hash(hash, entries[i]->name, (long)entries[i]);
71        }
72        entries[i]->group_nr = -1;
73    }
74
75    long groupcnt = 0;
76    DI_ENTRY **groups = new DI_ENTRY *[nentries];
77    search_group(tree,hash,&groupcnt,0,groups); // search a group for all species and create groups
78
79    DI_ENTRY **found_groups = 0;
80
81    if (groupcnt) { // if we found groups => make copy of group array
82        found_groups = new DI_ENTRY *[groupcnt];
83        memcpy(found_groups, groups, groupcnt*sizeof(*groups));
84    }
85
86    int nongroupcnt = 0; // count # of species NOT in groups and copy then to 'groups'
87    for (i=0;i<nentries;i++) {
88        if (entries[i]->name && entries[i]->group_nr == -1) { // species not in groups
89            groups[nongroupcnt] = new DI_ENTRY(entries[i]->name,this);
90            entries[i]->group_nr = nongroupcnt++;
91        }
92        else { // species is in group => add nentries to group_nr
93            entries[i]->group_nr = entries[i]->group_nr + nentries;
94        }
95    }
96
97    // append groups to end of 'groups'
98    if (groupcnt) {
99        memcpy(groups+nongroupcnt, found_groups, groupcnt*sizeof(*groups)); // copy groups to end of 'groups'
100        delete [] found_groups;
101        found_groups = 0;
102
103        for (i=0; i<nentries; i++) {
104            if (entries[i]->name && entries[i]->group_nr>=nentries) {
105                entries[i]->group_nr = entries[i]->group_nr - nentries + nongroupcnt; // correct group_nr's for species in groups
106            }
107        }
108    }
109
110    groupcnt += nongroupcnt; // now groupcnt is # of groups + # of non-group-species
111
112    AP_smatrix count(groupcnt);
113    AP_smatrix *sum = new AP_smatrix(groupcnt);
114
115    // Now we have create a new DI_ENTRY table, let's do the matrix
116    for (i=0;i<nentries;i++){
117        for (j=0;j<=i;j++) {
118            int x = entries[i]->group_nr;   if (x<0) continue;
119            int y = entries[j]->group_nr;   if (y<0) continue;
120            // x,y are the destination i,j
121            count.set(x,y,count.get(x,y)+1.0);
122            sum->set(x,y,sum->get(x,y)+matrix->get(i,j));
123        }
124    }
125
126    for (i=0;i<groupcnt;i++){       // get the arithmetic average
127        for (j=0;j<=i;j++) {
128            AP_FLOAT c = count.get(i,j);
129            if (c > 0) {
130                sum->set(i,j, sum->get(i,j) / c);
131            }
132        }
133    }
134    delete matrix;
135    matrix = sum;
136
137    for (i=0;i<nentries;i++) {  // delete everything
138        delete entries[i];
139        entries[i] = 0;
140    }
141    free(entries);
142
143    entries = groups;
144    nentries = groupcnt;
145    entries_mem_size = groupcnt;
146    matrix_type = DI_MATRIX_COMPRESSED;
147
148    GBS_free_hash(hash);
149    return error;
150}
Note: See TracBrowser for help on using the browser.