diff --git a/cell_tree.hpp b/cell_tree.hpp index bcacb25c171f31439f0c4711649fccfd36ab8642..3daf48d56620725dae2bb44cb47dfe318b4ab0c5 100644 --- a/cell_tree.hpp +++ b/cell_tree.hpp @@ -49,14 +49,32 @@ class cell_tree { } /// construct from a tree + // copy constructor cell_tree(tree const& t) : tree_(t) - {} + { } - /// construct from a tree + // move constructor cell_tree(tree&& t) : tree_(std::move(t)) - {} + { } + + /// construct from a cell tree + // copy constructor + cell_tree(cell_tree const& other) + : tree_(other.tree_), + soma_(other.soma()) + { } + + // move constructor + cell_tree(cell_tree&& other) + : tree_(std::move(other.tree_)), + soma_(other.soma()) + { } + + int_type soma() const { + return soma_; + } /// Minimize the depth of the tree. int_type balance() { @@ -64,7 +82,12 @@ class cell_tree { auto new_root = find_minimum_root(); // change the root on the tree - tree_.change_root(new_root); + auto p = tree_.change_root(new_root); + + // keep track of the soma_ + if(p.size()) { + soma_ = p[soma_]; + } return new_root; } @@ -241,4 +264,6 @@ class cell_tree { // storage for the tree structure of cell segments tree tree_; + + int_type soma_ = 0; }; diff --git a/main.cpp b/main.cpp index b0e32dc5b3018af31568551b891abece4608c8ca..1f70eac1836949b320a1c01d7f8baa0eb16126db 100644 --- a/main.cpp +++ b/main.cpp @@ -138,13 +138,13 @@ TEST(tree, change_root) { std::vector<int> parent_index = {0,0,0}; tree t; t.init_from_parent_index(parent_index); - auto new_tree = t.change_root(1); + t.change_root(1); - EXPECT_EQ(new_tree.num_nodes(), 3); + EXPECT_EQ(t.num_nodes(), 3); - EXPECT_EQ(new_tree.num_children(0), 1); - EXPECT_EQ(new_tree.num_children(1), 1); - EXPECT_EQ(new_tree.num_children(2), 0); + EXPECT_EQ(t.num_children(0), 1); + EXPECT_EQ(t.num_children(1), 1); + EXPECT_EQ(t.num_children(2), 0); } { // a cell with the following structure @@ -157,15 +157,15 @@ TEST(tree, change_root) { std::vector<int> parent_index = {0,0,0,1,1}; tree t; t.init_from_parent_index(parent_index); - auto new_tree = t.change_root(1); + t.change_root(1); - EXPECT_EQ(new_tree.num_nodes(), 5); + EXPECT_EQ(t.num_nodes(), 5); - EXPECT_EQ(new_tree.num_children(0), 3); - EXPECT_EQ(new_tree.num_children(1), 0); - EXPECT_EQ(new_tree.num_children(2), 0); - EXPECT_EQ(new_tree.num_children(3), 1); - EXPECT_EQ(new_tree.num_children(4), 0); + EXPECT_EQ(t.num_children(0), 3); + EXPECT_EQ(t.num_children(1), 0); + EXPECT_EQ(t.num_children(2), 0); + EXPECT_EQ(t.num_children(3), 1); + EXPECT_EQ(t.num_children(4), 0); } { // a cell with the following structure @@ -183,19 +183,17 @@ TEST(tree, change_root) { tree t; t.init_from_parent_index(parent_index); - auto new_tree = t.change_root(1); + t.change_root(1); - EXPECT_EQ(new_tree.num_nodes(), 7); + EXPECT_EQ(t.num_nodes(), 7); - EXPECT_EQ(new_tree.num_children(0), 3); - EXPECT_EQ(new_tree.num_children(1), 0); - EXPECT_EQ(new_tree.num_children(2), 2); - EXPECT_EQ(new_tree.num_children(3), 0); - EXPECT_EQ(new_tree.num_children(4), 0); - EXPECT_EQ(new_tree.num_children(5), 1); - EXPECT_EQ(new_tree.num_children(6), 0); - - auto T = cell_tree(new_tree); + EXPECT_EQ(t.num_children(0), 3); + EXPECT_EQ(t.num_children(1), 0); + EXPECT_EQ(t.num_children(2), 2); + EXPECT_EQ(t.num_children(3), 0); + EXPECT_EQ(t.num_children(4), 0); + EXPECT_EQ(t.num_children(5), 1); + EXPECT_EQ(t.num_children(6), 0); } } @@ -215,7 +213,24 @@ TEST(cell_tree, balance) { t.balance(); + // the soma (original root) has moved to 5 in the new tree + EXPECT_EQ(t.soma(), 5); + EXPECT_EQ(t.num_segments(), 7); + EXPECT_EQ(t.num_children(0),3); + EXPECT_EQ(t.num_children(1),0); + EXPECT_EQ(t.num_children(2),2); + EXPECT_EQ(t.num_children(3),0); + EXPECT_EQ(t.num_children(4),0); + EXPECT_EQ(t.num_children(5),1); + EXPECT_EQ(t.num_children(6),0); + EXPECT_EQ(t.parent(0),-1); + EXPECT_EQ(t.parent(1), 0); + EXPECT_EQ(t.parent(2), 0); + EXPECT_EQ(t.parent(3), 0); + EXPECT_EQ(t.parent(4), 2); + EXPECT_EQ(t.parent(5), 2); + EXPECT_EQ(t.parent(6), 5); t.to_graphviz("cell.dot"); } diff --git a/tree.hpp b/tree.hpp index a548b346c86a3910df2574956644983e4446e8c9..b67244c721d97ad0084df57612d09c62e6f55f5f 100644 --- a/tree.hpp +++ b/tree.hpp @@ -175,12 +175,12 @@ class tree { return sizeof(int_type)*data_.size() + sizeof(tree); } - tree change_root(int b) { + index_type change_root(int b) { assert(b<num_nodes()); // no need to rebalance if the root node has been requested if(b==0) { - return tree(*this); + return index_type(); } // create new tree with memory allocated @@ -188,6 +188,7 @@ class tree { new_tree.init(num_nodes()); // add the root node + new_tree.data_(memory::all) = -std::numeric_limits<int_type>::min(); new_tree.parents_[0] = -1; new_tree.child_index_[0] = 0; @@ -205,13 +206,12 @@ class tree { new_tree.children_.begin(), [&p] (int i) {return p[i];} ); - // copy in new data - // this should be done with a swap, to avoid a malloc-free, however - // using std::swap gives a seg fault... todo - data_ = new_tree.data_; - //std::swap(data_, new_tree.data_); + // copy in new data with a move because the information in + // new_tree is not kept + std::swap(data_, new_tree.data_); + set_ranges(new_tree.num_nodes()); - return new_tree; + return p; } private : @@ -289,11 +289,13 @@ class tree { for(auto b : old_children) { if(b != parent_node) { children_[pos++] = b; + parents_[pos] = new_node; } } // then add the node's parent as a child if applicable if(add_parent_as_child) { children_[pos++] = old_tree.parent(old_node); + parents_[pos] = new_node; } child_index_[this_node+1] = pos;