root/trunk/DIST/DI_compress_matrix.cxx

Revision 7811, 4.3 KB (checked in by westram, 10 months ago)

merge from dev [7748] [7749] [7750]

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