source: tags/arb-6.0/NTREE/NT_sort.cxx

Last change on this file was 12267, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : NT_sort.cxx                                       //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "NT_local.h"
12#include "NT_cb.h"
13
14#include <item_sel_list.h>
15#include <aw_awar.hxx>
16#include <arb_progress.h>
17#include <aw_msg.hxx>
18#include <aw_root.hxx>
19#include <arbdbt.h>
20#include <arb_sort.h>
21
22#define NT_RESORT_FILTER (1<<GB_STRING)|(1<<GB_INT)|(1<<GB_FLOAT)
23
24#define CUSTOM_CRITERIA 3
25
26struct customCriterion {
27    char *key;
28    bool  reverse;
29
30    customCriterion() : key(NULL), reverse(false) {}
31    customCriterion(const char *key_, bool reverse_) : key(strdup(key_)), reverse(reverse_) {}
32    customCriterion(const customCriterion& other) : key(strdup(other.key)), reverse(other.reverse) {}
33    DECLARE_ASSIGNMENT_OPERATOR(customCriterion);
34    ~customCriterion() { free(key); }
35};
36
37static int cmpByKey(GBDATA *gbd1, GBDATA *gbd2, const customCriterion& by) {
38    GBDATA *gb_field1 = GB_entry(gbd1, by.key);
39    GBDATA *gb_field2 = GB_entry(gbd2, by.key);
40
41    int cmp;
42    if (gb_field1) {
43        if (gb_field2) {
44            switch (GB_read_type(gb_field1)) {
45                case GB_STRING: {
46                    const char *s1 = GB_read_char_pntr(gb_field1);
47                    const char *s2 = GB_read_char_pntr(gb_field2);
48
49                    cmp = strcmp(s1, s2);
50                    break;
51                }
52                case GB_FLOAT: {
53                    double d1 = GB_read_float(gb_field1);
54                    double d2 = GB_read_float(gb_field2);
55
56                    cmp = d1<d2 ? -1 : (d1>d2 ? 1 : 0);
57                    break;
58                }
59                case GB_INT: {
60                    int i1 = GB_read_int(gb_field1);
61                    int i2 = GB_read_int(gb_field2);
62
63                    cmp = i1-i2;
64                    break;
65                }
66                default:
67                    cmp = 0; // other field type -> no idea how to compare
68                    break;
69            }
70
71            if (by.reverse) cmp = -cmp;
72        }
73        else cmp = -1;           // existing < missing!
74    }
75    else cmp = gb_field2 ? 1 : 0;
76
77    return cmp;
78}
79
80static int resort_data_by_customOrder(const void *v1, const void *v2, void *cd_sortBy) {
81    GBDATA *gbd1 = (GBDATA*)v1;
82    GBDATA *gbd2 = (GBDATA*)v2;
83
84    const customCriterion *sortBy = (const customCriterion *)cd_sortBy;
85
86    int cmp = 0;
87    for (int c = 0; !cmp && c<CUSTOM_CRITERIA; ++c) {
88        cmp = cmpByKey(gbd1, gbd2, sortBy[c]);
89    }
90    return cmp;
91}
92
93
94static GBDATA **gb_resort_data_list;
95static long    gb_resort_data_count;
96
97static void NT_resort_data_base_by_tree(GBT_TREE *tree, GBDATA *gb_species_data) {
98    if (tree) {
99        if (tree->is_leaf) {
100            if (tree->gb_node) {
101                gb_resort_data_list[gb_resort_data_count++] = tree->gb_node;
102            }
103        }
104        else {
105            NT_resort_data_base_by_tree(tree->leftson, gb_species_data);
106            NT_resort_data_base_by_tree(tree->rightson, gb_species_data);
107        }
108    }
109}
110
111
112static GB_ERROR NT_resort_data_base(GBT_TREE *tree, const customCriterion *sortBy) {
113    nt_assert(contradicted(tree, sortBy));
114
115    GB_ERROR error = GB_begin_transaction(GLOBAL.gb_main);
116    if (!error) {
117        GBDATA *gb_sd     = GBT_get_species_data(GLOBAL.gb_main);
118        if (!gb_sd) error = GB_await_error();
119        else {
120            if (tree) {
121                gb_resort_data_count = 0;
122                gb_resort_data_list  = (GBDATA **)calloc(sizeof(GBDATA *), GB_nsons(gb_sd) + 256);
123                NT_resort_data_base_by_tree(tree, gb_sd);
124            }
125            else {
126                gb_resort_data_list = GBT_gen_species_array(GLOBAL.gb_main, &gb_resort_data_count);
127                GB_sort((void **)gb_resort_data_list, 0, gb_resort_data_count, resort_data_by_customOrder, (void*)sortBy);
128
129            }
130            error = GB_resort_data_base(GLOBAL.gb_main, gb_resort_data_list, gb_resort_data_count);
131            free(gb_resort_data_list);
132        }
133    }
134    return GB_end_transaction(GLOBAL.gb_main, error);
135}
136
137void NT_resort_data_by_phylogeny(AW_window *, AW_CL cl_ntw, AW_CL) {
138    arb_progress  progress("Sorting data");
139    GB_ERROR      error = 0;
140    GBT_TREE     *tree  = nt_get_tree_root_of_canvas((AWT_canvas*)cl_ntw);
141
142    if (!tree)  error = "Please select/build a tree first";
143    if (!error) error = NT_resort_data_base(tree, NULL);
144    if (error) aw_message(error);
145}
146
147#define AWAR_TREE_SORT1 "ad_tree/sort_1"
148#define AWAR_TREE_SORT2 "ad_tree/sort_2"
149#define AWAR_TREE_SORT3 "ad_tree/sort_3"
150
151#define AWAR_TREE_REV1 "ad_tree/rev1"
152#define AWAR_TREE_REV2 "ad_tree/rev2"
153#define AWAR_TREE_REV3 "ad_tree/rev3"
154
155static void NT_resort_data_by_user_criteria(AW_window *aw) {
156    arb_progress progress("Sorting data");
157
158    AW_root *aw_root = aw->get_root();
159
160    customCriterion sortBy[CUSTOM_CRITERIA];
161    sortBy[0] = customCriterion(aw_root->awar(AWAR_TREE_SORT1)->read_char_pntr(), aw_root->awar(AWAR_TREE_REV1)->read_int());
162    sortBy[1] = customCriterion(aw_root->awar(AWAR_TREE_SORT2)->read_char_pntr(), aw_root->awar(AWAR_TREE_REV2)->read_int());
163    sortBy[2] = customCriterion(aw_root->awar(AWAR_TREE_SORT3)->read_char_pntr(), aw_root->awar(AWAR_TREE_REV3)->read_int());
164
165    GB_ERROR error = NT_resort_data_base(NULL, sortBy);
166    if (error) aw_message(error);
167}
168
169void NT_create_resort_awars(AW_root *awr, AW_default aw_def) {
170    awr->awar_string(AWAR_TREE_SORT1, "name",      aw_def);
171    awr->awar_string(AWAR_TREE_SORT2, "full_name", aw_def);
172    awr->awar_string(AWAR_TREE_SORT3, "",          aw_def);
173
174    awr->awar_int(AWAR_TREE_REV1, 0, aw_def);
175    awr->awar_int(AWAR_TREE_REV2, 0, aw_def);
176    awr->awar_int(AWAR_TREE_REV3, 0, aw_def);
177}
178
179AW_window *NT_create_resort_window(AW_root *awr) {
180    AW_window_simple *aws = new AW_window_simple;
181    aws->init(awr, "SORT_DATABASE", "SORT DATABASE");
182    aws->load_xfig("nt_sort.fig");
183
184    aws->callback((AW_CB0)AW_POPDOWN);
185    aws->at("close");
186    aws->create_button("CLOSE", "CLOSE", "C");
187
188    aws->callback(makeHelpCallback("sp_sort_fld.hlp"));
189    aws->at("help");
190    aws->create_button("HELP", "HELP", "H");
191
192    create_selection_list_on_itemfields(GLOBAL.gb_main, aws, AWAR_TREE_SORT1, true, NT_RESORT_FILTER, "key1", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
193    create_selection_list_on_itemfields(GLOBAL.gb_main, aws, AWAR_TREE_SORT2, true, NT_RESORT_FILTER, "key2", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
194    create_selection_list_on_itemfields(GLOBAL.gb_main, aws, AWAR_TREE_SORT3, true, NT_RESORT_FILTER, "key3", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
195
196    aws->at("rev1"); aws->label("Reverse"); aws->create_toggle(AWAR_TREE_REV1);
197    aws->at("rev2"); aws->label("Reverse"); aws->create_toggle(AWAR_TREE_REV2);
198    aws->at("rev3"); aws->label("Reverse"); aws->create_toggle(AWAR_TREE_REV3);
199
200    aws->at("go");
201    aws->callback((AW_CB0)NT_resort_data_by_user_criteria);
202    aws->create_button("GO", "GO", "G");
203
204    return aws;
205}
Note: See TracBrowser for help on using the repository browser.