source: branches/profile/SL/ARB_TREE/ARB_Tree.cxx

Last change on this file was 12138, checked in by westram, 11 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 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) {
138            error = get_root_node()->add_delete_cb_rec(arb_tree_species_deleted_cb);
139        }
140        if (!error && ali->has_data() && seqTemplate) {
141            error = get_root_node()->preloadLeafSequences();
142        }
143        if (!error) isLinkedToDB = true;
144    }
145    return error;
146}
147
148void ARB_seqtree_root::unlinkFromDB() {
149    if (isLinkedToDB) {
150        if (addDeleteCallbacks) get_root_node()->remove_delete_cb_rec(arb_tree_species_deleted_cb);
151        GBT_unlink_tree(get_root_node());
152        if (ali->has_data() && seqTemplate) get_root_node()->unloadSequences();
153        isLinkedToDB = false;
154    }
155}
156
157// ----------------------
158//      ARB_tree_info
159
160ARB_tree_info::ARB_tree_info() {
161    memset(this, 0, sizeof(*this));
162}
163
164void ARB_seqtree::calcTreeInfo(ARB_tree_info& info) {
165    if (is_leaf) {
166        info.leafs++;
167        if (gb_node) {
168            if (GB_read_flag(gb_node)) info.marked++;
169        }
170        else {
171            info.unlinked++;
172        }
173    }
174    else {
175        info.innerNodes++;
176        if (gb_node) info.groups++;
177        get_leftson()->calcTreeInfo(info);
178        get_rightson()->calcTreeInfo(info);
179    }
180}
181
182// ---------------------
183//      ARB_seqtree
184
185ARB_seqtree::~ARB_seqtree() {
186    delete seq;
187}
188
189void ARB_seqtree::mark_subtree() {
190    if (is_leaf) {
191        if (gb_node) GB_write_flag(gb_node, 1);
192    }
193    else {
194        get_leftson()->mark_subtree();
195        get_rightson()->mark_subtree();
196    }
197}
198
199bool ARB_seqtree::contains_marked_species() {
200    if (is_leaf) {
201        return gb_node && GB_read_flag(gb_node) != 0;
202    }
203    return
204        get_leftson()->contains_marked_species() ||
205        get_rightson()->contains_marked_species();
206}
207
208GB_ERROR ARB_seqtree::add_delete_cb_rec(ARB_tree_node_del_cb cb) {
209    GB_ERROR error = NULL;
210    if (is_leaf) {
211        if (gb_node) {
212            error = GB_add_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
213        }
214    }
215    else {
216        error            = get_leftson() ->add_delete_cb_rec(cb);
217        if (error) error = get_rightson()->add_delete_cb_rec(cb);
218    }
219    return error;
220}
221
222void ARB_seqtree::remove_delete_cb_rec(ARB_tree_node_del_cb cb) {
223    if (is_leaf) {
224        if (gb_node) GB_remove_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
225    }
226    else {
227        get_leftson() ->remove_delete_cb_rec(cb);
228        get_rightson()->remove_delete_cb_rec(cb);
229    }
230
231}
232
233GB_ERROR ARB_seqtree::preloadLeafSequences() {
234    GB_ERROR error;
235    if (is_leaf) {
236        if (gb_node) {
237            seq   = get_tree_root()->get_seqTemplate()->dup();
238            error = seq->bind_to_species(gb_node); // does not load sequences yet
239        }
240    }
241    else {
242        error             = get_leftson()->preloadLeafSequences();
243        if (!error) error = get_rightson()->preloadLeafSequences();
244    }
245    return error;
246}
247
248void ARB_seqtree::unloadSequences() {
249    delete seq;
250    seq = NULL;
251    if (!is_leaf) {
252        get_leftson()->unloadSequences();
253        get_rightson()->unloadSequences();
254    }
255}
256
257void ARB_seqtree::replace_seq(AP_sequence *sequence) {
258    if (seq) {
259        delete seq;
260        seq = 0;
261    }
262    set_seq(sequence);
263}
264
265// ------------------------
266//      ARB_countedTree
267
268size_t ARB_countedTree::relative_position_in(const ARB_countedTree *upgroup) const {
269    at_assert(is_inside(upgroup));
270
271    size_t pos = 0;
272    if (this != upgroup) {
273        pos = is_upper_son() ? 0 : get_brother()->get_leaf_count();
274        pos += get_father()->relative_position_in(upgroup);
275    }
276    return pos;
277}
278
Note: See TracBrowser for help on using the repository browser.