source: tags/ms_r16q2/NTREE/NT_branchAnalysis.cxx

Last change on this file was 14686, checked in by westram, 8 years ago
  • change datatypes used in awar-access (only changed simple cases)
File size: 10.5 KB
Line 
1// ============================================================== //
2//                                                                //
3//   File      : NT_branchAnalysis.cxx                            //
4//   Purpose   :                                                  //
5//                                                                //
6//   Coded by Ralf Westram (coder@reallysoft.de) in August 2012   //
7//   Institute of Microbiology (Technical University Munich)      //
8//   http://www.arb-home.de/                                      //
9//                                                                //
10// ============================================================== //
11
12#include "NT_local.h"
13#include <TreeCallbacks.hxx>
14#include <aw_awar.hxx>
15#include <awt_canvas.hxx>
16#include <aw_msg.hxx>
17#include <aw_root.hxx>
18#include <awt_config_manager.hxx>
19
20#define AWAR_BRANCH_ANALYSIS     "branch_analysis"
21#define AWAR_BRANCH_ANALYSIS_TMP "tmp/" AWAR_BRANCH_ANALYSIS
22
23#define AWAR_BA_MIN_REL_DIFF AWAR_BRANCH_ANALYSIS "/min_rel_diff"
24#define AWAR_BA_MIN_ABS_DIFF AWAR_BRANCH_ANALYSIS "/min_abs_diff"
25#define AWAR_BA_MIN_DEPTH    AWAR_BRANCH_ANALYSIS "/min_depth"
26#define AWAR_BA_MIN_ROOTDIST AWAR_BRANCH_ANALYSIS "/min_rootdist"
27#define AWAR_BA_DEGENERATION AWAR_BRANCH_ANALYSIS "/degeneration"
28
29#define AWAR_BA_AUTOMARK_FORMAT AWAR_BRANCH_ANALYSIS_TMP "/auto_%s"
30
31// AISC_MKPT_PROMOTE:class AWT_canvas;
32
33class BranchWindow : virtual Noncopyable {
34    AWT_canvas       *ntw;
35    char             *suffix;
36    AW_awar          *awar_info;
37    AW_window_simple *aws;
38
39    static char *get_suffix(AWT_canvas *ntw) {
40        // suffix depends on canvas
41        return GBS_global_string_copy("_%i", NT_get_canvas_id(ntw));
42    }
43
44    const char *local_awar_name (const char *prefix, const char *name) { return GBS_global_string("%s%s/%s", prefix, suffix, name); }
45
46    void create_awars(AW_root *aw_root);
47    void create_window(AW_root *aw_root);
48
49    const char *automark_awarname() const { return GBS_global_string(AWAR_BA_AUTOMARK_FORMAT, suffix); }
50
51public:
52    BranchWindow(AW_root *aw_root, AWT_canvas *ntw_)
53        : ntw(ntw_),
54          suffix(get_suffix(ntw))
55    {
56        create_awars(aw_root);
57        create_window(aw_root);
58    }
59
60    ~BranchWindow() {
61        free(suffix);
62    }
63
64    AW_window *get_window() const { return aws; }
65
66private:
67    AW_root *get_awroot() const { return get_window()->get_root(); }
68    AWT_canvas *get_canvas() const { return ntw; }
69    AP_tree *get_tree() const { return AWT_TREE(ntw)->get_root_node(); }
70    GBDATA *get_gbmain() const { return get_canvas()->gb_main; }
71    AW_awar *awar(const char *name) { return get_awroot()->awar(name); }
72
73    void postmark_action() const {
74        get_tree()->compute_tree();
75        get_canvas()->refresh();
76    }
77
78    bool have_tree() {
79        if (get_tree()) return true;
80        set_info("No tree selected");
81        return false;
82    }
83
84public:
85    void set_info(const char *msg) const { awar_info->write_string(msg); }
86    void unmark_all() const { NT_mark_all_cb(NULL, get_canvas(), 0); }
87
88    AW_awar *automark_awar() const { return get_awroot()->awar(automark_awarname()); }
89    bool has_automark_set() const { return automark_awar()->read_int(); }
90
91    void markDegeneratedBranches() {
92        if (have_tree()) {
93            GB_transaction ta(get_gbmain());
94            float          degeneration_factor = awar(AWAR_BA_DEGENERATION)->read_float();
95
96            unmark_all();
97            set_info(get_tree()->mark_degenerated_branches(degeneration_factor));
98            postmark_action();
99        }
100    }
101    void markDeepLeafs() {
102        if (have_tree()) {
103            GB_transaction ta(get_gbmain());
104
105            int   min_depth    = awar(AWAR_BA_MIN_DEPTH)->read_int();
106            float min_rootdist = awar(AWAR_BA_MIN_ROOTDIST)->read_float();
107
108            unmark_all();
109            set_info(get_tree()->mark_deep_leafs(min_depth, min_rootdist));
110            postmark_action();
111        }
112    }
113    void markLongBranches() {
114        if (have_tree()) {
115            GB_transaction ta(get_gbmain());
116
117            float min_rel_diff = awar(AWAR_BA_MIN_REL_DIFF)->read_float()/100.0;
118            float min_abs_diff = awar(AWAR_BA_MIN_ABS_DIFF)->read_float();
119
120            unmark_all();
121            set_info(get_tree()->mark_long_branches(min_rel_diff, min_abs_diff));
122            postmark_action();
123        }
124    }
125
126    void analyseDistances() {
127        if (have_tree()) {
128            GB_transaction ta(get_gbmain());
129            set_info(get_tree()->analyse_distances());
130        }
131    }
132};
133
134static BranchWindow *existingBranchWindow[MAX_NT_WINDOWS] = { MAX_NT_WINDOWS_NULLINIT };
135
136// --------------------------------------------------------------------------------
137
138static void mark_long_branches_cb       (AW_window*, BranchWindow *bw) { bw->markLongBranches(); }
139static void mark_deep_leafs_cb          (AW_window*, BranchWindow *bw) { bw->markDeepLeafs(); }
140static void mark_degenerated_branches_cb(AW_window*, BranchWindow *bw) { bw->markDegeneratedBranches(); }
141static void unmark_branches_cb          (AW_window*, BranchWindow *bw) { bw->unmark_all(); }
142static void distance_analysis_cb        (AW_window*, BranchWindow *bw) { bw->analyseDistances(); }
143
144static void tree_changed_cb             (AW_root*,   BranchWindow *bw) { bw->set_info("<tree has changed>"); }
145
146static BranchWindow *findAutomarkingBranchWindow() {
147    for (int w = 0; w<MAX_NT_WINDOWS; ++w) {
148        BranchWindow *bw = existingBranchWindow[w];
149        if (bw && bw->has_automark_set()) {
150            return bw;
151        }
152    }
153    return NULL;
154}
155
156static void mark_long_branches_automark_cb() {
157    BranchWindow *bw = findAutomarkingBranchWindow();
158    if (bw) bw->markLongBranches();
159}
160static void mark_deep_leafs_automark_cb() {
161    BranchWindow *bw = findAutomarkingBranchWindow();
162    if (bw) bw->markDeepLeafs();
163}
164static void mark_degenerated_branches_automark_cb() {
165    BranchWindow *bw = findAutomarkingBranchWindow();
166    if (bw) bw->markDegeneratedBranches();
167}
168
169static void automark_changed_cb(AW_root *, BranchWindow *bw) {
170    static bool avoid_recursion = false;
171    if (!avoid_recursion) {
172        AW_awar *awar_automark = bw->automark_awar();
173        if (awar_automark->read_int()) { // just activated
174            LocallyModify<bool> avoid(avoid_recursion, true);
175
176            awar_automark->write_int(0);
177            BranchWindow *prev_active = findAutomarkingBranchWindow();
178            if (prev_active) prev_active->automark_awar()->write_int(0);
179            awar_automark->write_int(1);
180        }
181    }
182}
183
184void BranchWindow::create_awars(AW_root *aw_root) {
185    awar_info = aw_root->awar_string(local_awar_name(AWAR_BRANCH_ANALYSIS_TMP, "info"), "<No analysis performed yet>");
186    aw_root->awar(ntw->user_awar)->add_callback(makeRootCallback(tree_changed_cb, this));
187
188    aw_root->awar_float(AWAR_BA_MIN_REL_DIFF, 75)->set_minmax(0, 100)->add_callback(makeRootCallback(mark_long_branches_automark_cb));
189    aw_root->awar_float(AWAR_BA_MIN_ABS_DIFF, 0.01)->set_minmax(0, 20)->add_callback(makeRootCallback(mark_long_branches_automark_cb));
190
191    aw_root->awar_int(AWAR_BA_MIN_DEPTH, 0)->set_minmax(0, 50)->add_callback(makeRootCallback(mark_deep_leafs_automark_cb));
192    aw_root->awar_float(AWAR_BA_MIN_ROOTDIST, 0.9)->set_minmax(0, 20)->add_callback(makeRootCallback(mark_deep_leafs_automark_cb));
193
194    aw_root->awar_float(AWAR_BA_DEGENERATION, 30)->set_minmax(0, 100)->add_callback(makeRootCallback(mark_degenerated_branches_automark_cb));
195}
196
197static AWT_config_mapping_def branch_analysis_config_mapping[] = {
198    { AWAR_BA_MIN_REL_DIFF, "minreldiff" },
199    { AWAR_BA_MIN_ABS_DIFF, "minabsdiff" },
200    { AWAR_BA_MIN_DEPTH,    "mindepth" },
201    { AWAR_BA_MIN_ROOTDIST, "minrootdist" },
202    { AWAR_BA_DEGENERATION, "degeneration" },
203
204    { 0, 0 }
205};
206
207void BranchWindow::create_window(AW_root *aw_root) {
208    aws = new AW_window_simple;
209
210    aws->init(aw_root, GBS_global_string("BRANCH_ANALYSIS_%s", suffix), "Branch analysis");
211    aws->load_xfig("ad_branch.fig");
212
213    aws->auto_space(5, 5);
214
215    aws->at("close");
216    aws->callback(AW_POPDOWN);
217    aws->create_button("CLOSE", "CLOSE", "C");
218
219    aws->at("help");
220    aws->callback(makeHelpCallback("branch_analysis.hlp"));
221    aws->create_button("HELP", "HELP", "H");
222
223    AW_awar *awar_automark = aw_root->awar_int(automark_awarname(), 0);
224    aws->at("auto");
225    aws->label("Auto mark?");
226    aws->create_toggle(awar_automark->awar_name);
227    awar_automark->add_callback(makeRootCallback(automark_changed_cb, this));
228
229    aws->at("sel");
230    aws->create_button(0, ntw->user_awar, 0, "+");
231
232    aws->at("info");
233    aws->create_text_field(awar_info->awar_name);
234
235    aws->button_length(28);
236   
237    aws->at("dist_analyse");
238    aws->callback(makeWindowCallback(distance_analysis_cb, this));
239    aws->create_button("ANALYSE", "Analyse distances in tree");
240
241    aws->at("unmark");
242    aws->callback(makeWindowCallback(unmark_branches_cb, this));
243    aws->create_button("UNMARK", "Unmark all species");
244
245    const int FIELDWIDTH  = 10;
246    const int SCALERWIDTH = 200;
247
248    aws->at("mark_long");
249    aws->callback(makeWindowCallback(mark_long_branches_cb, this));
250    aws->create_button("MARK_LONG", "Mark long branches");
251
252    aws->at("min_rel"); aws->create_input_field_with_scaler(AWAR_BA_MIN_REL_DIFF, FIELDWIDTH, SCALERWIDTH, AW_SCALER_LINEAR);
253    aws->at("min_abs"); aws->create_input_field_with_scaler(AWAR_BA_MIN_ABS_DIFF, FIELDWIDTH, SCALERWIDTH, AW_SCALER_EXP_LOWER);
254
255
256    aws->at("mark_deep");
257    aws->callback(makeWindowCallback(mark_deep_leafs_cb, this));
258    aws->create_button("MARK_DEEP", "Mark deep leafs");
259
260    aws->at("tree_depth");   aws->create_input_field_with_scaler(AWAR_BA_MIN_DEPTH, FIELDWIDTH, SCALERWIDTH, AW_SCALER_LINEAR);
261    aws->at("branch_depth"); aws->create_input_field_with_scaler(AWAR_BA_MIN_ROOTDIST, FIELDWIDTH, SCALERWIDTH, AW_SCALER_LINEAR);
262
263    aws->at("mark_degen");
264    aws->callback(makeWindowCallback(mark_degenerated_branches_cb, this));
265    aws->create_button("MARK_DEGENERATED", "Mark degenerated branches");
266
267    aws->at("degen"); aws->create_input_field_with_scaler(AWAR_BA_DEGENERATION, FIELDWIDTH, SCALERWIDTH, AW_SCALER_LINEAR);
268
269    aws->at("config");
270    AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "branch_analysis", branch_analysis_config_mapping);
271}
272
273AW_window *NT_create_branch_analysis_window(AW_root *aw_root, AWT_canvas *ntw) {
274    int ntw_id = NT_get_canvas_id(ntw);
275    if (!existingBranchWindow[ntw_id]) {
276        existingBranchWindow[ntw_id] = new BranchWindow(aw_root, ntw);
277    }
278    nt_assert(existingBranchWindow[ntw_id]);
279    return existingBranchWindow[ntw_id]->get_window();
280}
281
Note: See TracBrowser for help on using the repository browser.