Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic bp tree #490

Merged
merged 6 commits into from
Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions empress/support_files/js/bp-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
/**
* @type {Array}
* @private
* stores the name of each node in preorder. If names are not provided
* stores the name of each node in postorder. If names are not provided
* then the names will be set to null by default.
* Note: if memory becomes an issue this could be converted into a
* Uint16Array
Expand All @@ -85,7 +85,7 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
/**
* @type {Array}
* @private
* Stores the length of the nodes in preorder. If lengths are not
* Stores the length of the nodes in postorder. If lengths are not
* provided then lengths will be set to null.
*/
this.lengths_ = lengths ? lengths : null;
Expand Down Expand Up @@ -971,5 +971,64 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
return this._nameToNodes[name];
};

/**
* tips - Set
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fill the rest of the documentation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc added

*/
BPTree.prototype.shear = function (keepTips) {
// closure
var scope = this;

// create new names and lengths array
var names = [null];
var lengths = [null];

// create new bit array
var mask = [];

// function to that will set open/close bits for a node
var set_bits = (node) => {
mask[node] = 1;
mask[scope.close(node)] = 0;
};

// set root open/close bits
set_bits(this.root());

// iterate over bp tree in post order and add all tips that are in
// keepTips plus their ancestors
var i;
for (i = 1; i <= this.size; i++) {
var node = this.postorderselect(i);
var name = this.name(node);
if (this.isleaf(node) && keepTips.has(name)) {
// set open/close bits for tip
set_bits(node);

// set open/close bits for tips ancestors
var parent = this.parent(node);
while (parent !== this.root() || mask[parent] !== 1) {
set_bits(parent);
parent = this.parent(parent);
}
}
}

var newBitArray = [];
for (i = 0; i < mask.length; i++) {
if (mask[i] !== undefined) {
newBitArray.push(mask[i]);
}

// get name and length of node
// Note: names and lengths of nodes are stored in postorder

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

if (mask[i] === 0) {
names.push(this.name(i));
lengths.push(this.length(i));
}
}
return new BPTree(newBitArray, names, lengths, null);
};

return BPTree;
});
96 changes: 96 additions & 0 deletions tests/test-bp-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -877,5 +877,101 @@ require(["jquery", "ByteArray", "BPTree"], function ($, ByteArray, BPTree) {
"Error thrown when no length info given"
);
});

test("Test shear", function () {
// test modified from https://github.com/wasade/improved-octo-waddle/blob/master/bp/tests/test_bp.py#L228
// newick represenation
// ((3,4,(6)5)2, 7, ((10, 11)9)8)r;
var preShearArr = [
1,
1,
1,
0,
1,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
0,
1,
0,
0,
0,
0,
];
var preShearNames = [
null,
"3",
"4",
"6",
"5",
"2",
"7",
"10",
"11",
"9",
"8",
"r",
];
var preShearLenghts = [null, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
var preShearBPTree = new BPTree(
preShearArr,
preShearNames,
preShearLenghts,
null
);

var keep = new Set(["4", "6", "7", "10", "11"]);
var result = preShearBPTree.shear(keep);
deepEqual(result.b_, [
1,
1,
1,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
0,
1,
0,
0,
0,
0,
]);
deepEqual(result.names_, [
null,
"4",
"6",
"5",
"2",
"7",
"10",
"11",
"9",
"8",
"r",
]);
deepEqual(result.lengths_, [null, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);

keep = new Set(["7", "10", "11"]);
result = preShearBPTree.shear(keep);
deepEqual(result.b_, [1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0]);
deepEqual(result.names_, [null, "7", "10", "11", "9", "8", "r"]);
deepEqual(result.lengths_, [null, 6, 7, 8, 9, 10, 11]);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kwcantrell can you add a test case for when all tips are removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test added

});
});