source: trunk/SL/ARB_TREE/ARB_Tree.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: 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
16#include <ad_cb.h>
17
18using namespace std;
19
20// --------------------------
21//      ARB_seqtree_root
22
23static void tree_deleted_cbwrapper(GBDATA *gb_tree, ARB_seqtree_root *troot) {
24    troot->tree_deleted_cb(gb_tree);
25}
26
27
28ARB_seqtree_root::ARB_seqtree_root(AliView *aliView, AP_sequence *seqTempl, bool add_delete_callbacks)
29    : TreeRoot(false),
30      ali(aliView),
31      seqTemplate(seqTempl ? seqTempl->dup() : NULp),
32      tree_name(NULp),
33      gb_tree(NULp),
34      isLinkedToDB(false),
35      addDeleteCallbacks(add_delete_callbacks)
36{
37#if defined(DEBUG)
38    at_assert(ali);
39    if (seqTemplate) {
40        at_assert(ali->has_data());
41        at_assert(seqTemplate->get_aliview() == ali);
42    }
43    else {
44        at_assert(!ali->has_data());
45    }
46#endif // DEBUG
47}
48
49ARB_seqtree_root::~ARB_seqtree_root() {
50    delete ali;
51    delete seqTemplate;
52
53    if (gb_tree) GB_remove_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
54    free(tree_name);
55}
56
57void ARB_seqtree_root::tree_deleted_cb(GBDATA *gb_tree_del) {
58    if (gb_tree == gb_tree_del) {                   // ok - it's my tree
59        gb_tree = NULp;
60        freenull(tree_name);
61    }
62    else {
63        at_assert(0); // callback for wrong tree received
64    }
65}
66GB_ERROR ARB_seqtree_root::loadFromDB(const char *name) {
67    GBDATA   *gb_main = get_gb_main();
68    GB_ERROR  error   = GB_push_transaction(gb_main);
69
70    if (!error) {
71        ARB_seqtree *old_root = get_root_node();
72        if (old_root) {
73            change_root(old_root, NULp);
74            delete old_root;
75        }
76
77        if (gb_tree) {
78            GB_remove_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
79            gb_tree = NULp;
80            freenull(tree_name);
81        }
82
83        ARB_seqtree *arb_tree   = DOWNCAST(ARB_seqtree*, GBT_read_tree(gb_main, name, this));
84        if (!arb_tree) error = GB_await_error();
85        else {
86            gb_tree             = GBT_find_tree(gb_main, name);
87            if (!gb_tree) error = GB_await_error();
88            else {
89                error = GB_add_callback(gb_tree, GB_CB_DELETE, makeDatabaseCallback(tree_deleted_cbwrapper, this));
90                if (!error) {
91                    at_assert(arb_tree == arb_tree->get_root_node());
92                    at_assert(arb_tree == get_root_node());
93                    tree_name    = strdup(name);
94                    isLinkedToDB = false;
95                }
96                else {
97                    gb_tree = NULp;
98                }
99            }
100            if (error) delete arb_tree;
101        }
102    }
103
104    return GB_end_transaction(gb_main, error);
105}
106
107GB_ERROR ARB_seqtree_root::saveToDB() {
108    GB_ERROR error;
109    if (!gb_tree) {
110        error = "Can't save your tree (no tree loaded or tree has been deleted)";
111    }
112    else {
113        GBDATA *gb_main   = get_gb_main();
114        error             = GB_push_transaction(gb_main);
115        at_assert(get_root_node());
116        if (!error) error = GBT_overwrite_tree(gb_tree, get_root_node());
117        error             = GB_end_transaction(gb_main, error);
118    }
119    return error;
120}
121
122static void arb_tree_species_deleted_cb(GBDATA *gb_species, ARB_seqtree *arb_tree) {
123    // called whenever a species (which is linked to tree) gets deleted
124    at_assert(arb_tree->gb_node == gb_species);
125    if (arb_tree->gb_node == gb_species) {
126        arb_tree->gb_node = NULp; // unlink from tree
127    }
128}
129
130GB_ERROR ARB_seqtree_root::linkToDB(int *zombies, int *duplicates) {
131    at_assert(!ali->has_data() || get_seqTemplate()); // if ali has data, you have to set_seqTemplate() before linking
132
133    GB_ERROR error = NULp;
134    if (!isLinkedToDB) {
135        error = GBT_link_tree(get_root_node(), get_gb_main(), false, zombies, duplicates);
136        if (!error && addDeleteCallbacks) {
137            error = get_root_node()->add_delete_cb_rec(arb_tree_species_deleted_cb);
138        }
139        if (!error && ali->has_data() && seqTemplate) {
140            error = get_root_node()->preloadLeafSequences();
141        }
142        if (!error) isLinkedToDB = true;
143    }
144    return error;
145}
146
147void ARB_seqtree_root::unlinkFromDB() {
148    if (isLinkedToDB) {
149        if (addDeleteCallbacks) get_root_node()->remove_delete_cb_rec(arb_tree_species_deleted_cb);
150        GBT_unlink_tree(get_root_node());
151        if (ali->has_data() && seqTemplate) get_root_node()->unloadSequences();
152        isLinkedToDB = false;
153    }
154}
155
156// ----------------------
157//      ARB_tree_info
158
159ARB_tree_info::ARB_tree_info() {
160    memset(this, 0, sizeof(*this));
161}
162
163void ARB_seqtree::calcTreeInfo(ARB_tree_info& info) {
164    if (is_leaf()) {
165        info.leafs++;
166        if (gb_node) {
167            if (GB_read_flag(gb_node)) info.marked++;
168        }
169        else {
170            info.unlinked++;
171        }
172    }
173    else {
174        info.innerNodes++;
175        if (gb_node) info.groups++;
176        get_leftson()->calcTreeInfo(info);
177        get_rightson()->calcTreeInfo(info);
178    }
179}
180
181// ---------------------
182//      ARB_seqtree
183
184ARB_seqtree::~ARB_seqtree() {
185    delete seq;
186}
187
188void ARB_seqtree::mark_subtree() {
189    if (is_leaf()) {
190        if (gb_node) GB_write_flag(gb_node, 1);
191    }
192    else {
193        get_leftson()->mark_subtree();
194        get_rightson()->mark_subtree();
195    }
196}
197
198bool ARB_seqtree::contains_marked_species() {
199    if (is_leaf()) {
200        return gb_node && GB_read_flag(gb_node) != 0;
201    }
202    return
203        get_leftson()->contains_marked_species() ||
204        get_rightson()->contains_marked_species();
205}
206
207GB_ERROR ARB_seqtree::add_delete_cb_rec(ARB_tree_node_del_cb cb) {
208    GB_ERROR error = NULp;
209    if (is_leaf()) {
210        if (gb_node) {
211            error = GB_add_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
212        }
213    }
214    else {
215        error            = get_leftson() ->add_delete_cb_rec(cb);
216        if (error) error = get_rightson()->add_delete_cb_rec(cb);
217    }
218    return error;
219}
220
221void ARB_seqtree::remove_delete_cb_rec(ARB_tree_node_del_cb cb) {
222    if (is_leaf()) {
223        if (gb_node) GB_remove_callback(gb_node, GB_CB_DELETE, makeDatabaseCallback(cb, this));
224    }
225    else {
226        get_leftson() ->remove_delete_cb_rec(cb);
227        get_rightson()->remove_delete_cb_rec(cb);
228    }
229
230}
231
232GB_ERROR ARB_seqtree::preloadLeafSequences() {
233    GB_ERROR error = NULp;
234    if (is_leaf()) {
235        if (gb_node) {
236            seq   = get_tree_root()->get_seqTemplate()->dup();
237            error = seq->bind_to_species(gb_node); // does not load sequences yet
238        }
239    }
240    else {
241        error             = get_leftson()->preloadLeafSequences();
242        if (!error) error = get_rightson()->preloadLeafSequences();
243    }
244    return error;
245}
246
247void ARB_seqtree::unloadSequences() {
248    delete seq;
249    seq = NULp;
250    if (!is_leaf()) {
251        get_leftson()->unloadSequences();
252        get_rightson()->unloadSequences();
253    }
254}
255
256void ARB_seqtree::replace_seq(AP_sequence *sequence) {
257    if (seq) {
258        delete seq;
259        seq = NULp;
260    }
261    set_seq(sequence);
262}
263
264// ------------------------
265//      ARB_countedTree
266
267size_t ARB_countedTree::relative_position_in(const ARB_countedTree *upgroup) const {
268    at_assert(is_inside(upgroup));
269
270    size_t pos = 0;
271    if (this != upgroup) {
272        pos = is_upper_son() ? 0 : get_brother()->get_leaf_count();
273        pos += get_father()->relative_position_in(upgroup);
274    }
275    return pos;
276}
277
Note: See TracBrowser for help on using the repository browser.