source: trunk/DIST/DI_compress_matrix.cxx

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