source: tags/arb-6.0-rc1/SL/ARB_TREE/ARB_Tree.cxx

Last change on this file was 11488, checked in by westram, 10 years ago
  • reintegrates 'tree' into 'trunk'
    • implements #417 (multifurcate tree)
    • tree display
      • adds MULTIFURC MODE
      • reordered modes (synchronizes NTREE and PARSIMONY)
    • branch analysis
      • display number of multifurcations in 'mark long branches'
      • display "in-tree-distance" and "per-species-distance"
    • added function to toggle '100%' bootstraps
    • document bug in GBT_remove_leafs (#452)
  • adds:
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ARB_Tree.cxx                                      //
4//   Purpose   : Tree types with sequence knowledge                //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in October 2009   //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "ARB_Tree.hxx"
13
14#include <AP_filter.hxx>
15#include <AP_sequence.hxx>
16
17#include <ad_cb.h>
18
19using namespace std;
20
21// --------------------------
22//      ARB_seqtree_root
23
24static void tree_deleted_cbwrapper(GBDATA *gb_tree, ARB_seqtree_root *troot) {
25    troot->tree_deleted_cb(gb_tree);
26}
27
28
29ARB_seqtree_root::ARB_seqtree_root(AliView *aliView, RootedTreeNodeFactory *nodeMaker_, AP_sequence *seqTempl, bool add_delete_callbacks)
30    : TreeRoot(nodeMaker_, false),
31      ali(aliView),
32      seqTemplate(seqTempl ? seqTempl->dup() : NULL),
33      tree_name(NULL),
34      gb_tree(NULL),
35      isLinkedToDB(false),
36      addDeleteCallbacks(add_delete_callbacks)
37{
38#if defined(DEBUG)
39    at_assert(ali);
40    if (seqTemplate) {
41        at_assert(ali->has_data());
42        at_assert(seqTemplate->get_aliview() == ali);
43    }
44    else {
45        at_assert(!ali->has_data());
46    }
47#endif // DEBUG
48}
49
50ARB_seqtree_root::~ARB_seqtree_root() {
51    delete ali;
52    delete seqTemplate;
53
54    if (gb_tree) GB_remove_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
55    free(tree_name);
56}
57
58void ARB_seqtree_root::tree_deleted_cb(GBDATA *gb_tree_del) {
59    if (gb_tree == gb_tree_del) {                   // ok - it's my tree
60        gb_tree = NULL;
61        freenull(tree_name);
62    }
63    else {
64        at_assert(0); // callback for wrong tree received
65    }
66}
67GB_ERROR ARB_seqtree_root::loadFromDB(const char *name) {
68    GBDATA   *gb_main = get_gb_main();
69    GB_ERROR  error   = GB_push_transaction(gb_main);
70
71    if (!error) {
72        ARB_seqtree *old_root = get_root_node();
73        if (old_root) {
74            change_root(old_root, NULL);
75            delete old_root;
76        }
77
78        if (gb_tree) {
79            GB_remove_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
80            gb_tree = NULL;
81            freenull(tree_name);
82        }
83
84        ARB_seqtree *arb_tree   = DOWNCAST(ARB_seqtree*, GBT_read_tree(gb_main, name, *this));
85        if (!arb_tree) error = GB_await_error();
86        else {
87            gb_tree             = GBT_find_tree(gb_main, name);
88            if (!gb_tree) error = GB_await_error();
89            else {
90                error = GB_add_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
91                if (!error) {
92                    at_assert(arb_tree == arb_tree->get_root_node());
93                    at_assert(arb_tree == get_root_node());
94                    tree_name    = strdup(name);
95                    isLinkedToDB = false;
96                }
97                else {
98                    gb_tree = NULL;
99                }
100            }
101            if (error) delete arb_tree;
102        }
103    }
104
105    return GB_end_transaction(gb_main, error);
106}
107
108GB_ERROR ARB_seqtree_root::saveToDB() {
109    GB_ERROR error;
110    if (!gb_tree) {
111        error = "Can't save your tree (no tree loaded or tree has been deleted)";
112    }
113    else {
114        GBDATA *gb_main   = get_gb_main();
115        error             = GB_push_transaction(gb_main);
116        at_assert(get_root_node());
117        if (!error) error = GBT_overwrite_tree(gb_tree, get_root_node());
118        error             = GB_end_transaction(gb_main, error);
119    }
120    return error;
121}
122
123static void arb_tree_species_deleted_cb(GBDATA *gb_species, ARB_seqtree *arb_tree) {
124    // called whenever a species (which is linked to tree) gets deleted
125    at_assert(arb_tree->gb_node == gb_species);
126    if (arb_tree->gb_node == gb_species) {
127        arb_tree->gb_node = NULL; // unlink from tree
128    }
129}
130
131GB_ERROR ARB_seqtree_root::linkToDB(int *zombies, int *duplicates) {
132    at_assert(!ali->has_data() || get_seqTemplate()); // if ali has data, you have to set_seqTemplate() before linking
133
134    GB_ERROR error = 0;
135    if (!isLinkedToDB) {
136        error = GBT_link_tree(get_root_node(), get_gb_main(), false, zombies, duplicates);
137        if (!error && addDeleteCallbacks) error = get_root_node()->add_delete_cb_rec(arb_tree_species_deleted_cb);
138        if (!error) {
139            if (ali->has_data() && seqTemplate) get_root_node()->preloadLeafSequences();
140            isLinkedToDB = true;
141        }
142    }
143    return error;
144}
145
146void ARB_seqtree_root::unlinkFromDB() {
147    if (isLinkedToDB) {
148        if (addDeleteCallbacks) get_root_node()->remove_delete_cb_rec(arb_tree_species_deleted_cb);
149        GBT_unlink_tree(get_root_node());
150        if (ali->has_data() && seqTemplate) get_root_node()->unloadSequences();
151        isLinkedToDB = false;
152    }
153}
154
155// ----------------------
156//      ARB_tree_info
157
158ARB_tree_info::ARB_tree_info() {
159    memset(this, 0, sizeof(*this));
160}
161
162void ARB_seqtree::calcTreeInfo(ARB_tree_info& info) {
163    if (is_leaf) {
164        info.leafs++;
165        if (gb_node) {
166            if (GB_read_flag(gb_node)) info.marked++;
167        }
168        else {
169            info.unlinked++;
170        }
171    }
172    else {
173        info.innerNodes++;
174        if (gb_node) info.groups++;
175        get_leftson()->calcTreeInfo(info);
176        get_rightson()->calcTreeInfo(info);
177    }
178}
179
180// ---------------------
181//      ARB_seqtree
182
183ARB_seqtree::~ARB_seqtree() {
184    delete seq;
185}
186
187void ARB_seqtree::mark_subtree() {
188    if (is_leaf) {
189        if (gb_node) GB_write_flag(gb_node, 1);
190    }
191    else {
192        get_leftson()->mark_subtree();
193        get_rightson()->mark_subtree();
194    }
195}
196
197bool ARB_seqtree::contains_marked_species() {
198    if (is_leaf) {
199        return gb_node && GB_read_flag(gb_node) != 0;
200    }
201    return
202        get_leftson()->contains_marked_species() ||
203        get_rightson()->contains_marked_species();
204}
205
206GB_ERROR ARB_seqtree::add_delete_cb_rec(ARB_tree_node_del_cb cb) {
207    GB_ERROR error = NULL;
208    if (is_leaf) {
209        if (gb_node) {
210            error = GB_add_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
211        }
212    }
213    else {
214        error            = get_leftson() ->add_delete_cb_rec(cb);
215        if (error) error = get_rightson()->add_delete_cb_rec(cb);
216    }
217    return error;
218}
219
220void ARB_seqtree::remove_delete_cb_rec(ARB_tree_node_del_cb cb) {
221    if (is_leaf) {
222        if (gb_node) GB_remove_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
223    }
224    else {
225        get_leftson() ->remove_delete_cb_rec(cb);
226        get_rightson()->remove_delete_cb_rec(cb);
227    }
228
229}
230
231void ARB_seqtree::preloadLeafSequences() {
232    if (is_leaf) {
233        if (gb_node) {
234            seq = get_tree_root()->get_seqTemplate()->dup();
235            seq->bind_to_species(gb_node); // does not load sequences yet
236        }
237    }
238    else {
239        get_leftson()->preloadLeafSequences();
240        get_rightson()->preloadLeafSequences();
241    }
242}
243
244void ARB_seqtree::unloadSequences() {
245    delete seq;
246    seq = NULL;
247    if (!is_leaf) {
248        get_leftson()->unloadSequences();
249        get_rightson()->unloadSequences();
250    }
251}
252
253void ARB_seqtree::replace_seq(AP_sequence *sequence) {
254    if (seq) {
255        delete seq;
256        seq = 0;
257    }
258    set_seq(sequence);
259}
260
261// ------------------------
262//      ARB_countedTree
263
264size_t ARB_countedTree::relative_position_in(const ARB_countedTree *upgroup) const {
265    at_assert(is_inside(upgroup));
266
267    size_t pos = 0;
268    if (this != upgroup) {
269        pos = is_upper_son() ? 0 : get_brother()->get_leaf_count();
270        pos += get_father()->relative_position_in(upgroup);
271    }
272    return pos;
273}
274
Note: See TracBrowser for help on using the repository browser.