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

Shear UI #505

Merged
merged 75 commits into from
Jul 17, 2021
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
cbf4060
bp shear
kwcantrell Mar 1, 2021
227ec29
style fix
kwcantrell Mar 1, 2021
66c2e56
checkpoint
kwcantrell Mar 6, 2021
1183aa7
checkpoint
kwcantrell Mar 9, 2021
eafbea3
Finished TreeController
kwcantrell Mar 10, 2021
7301e82
tree-controller
kwcantrell Mar 17, 2021
888cf72
merged with master
kwcantrell Mar 17, 2021
f4f668f
fix doc issue
kwcantrell Mar 17, 2021
a408326
style fix
kwcantrell Mar 17, 2021
b043826
Apply suggestions from code review
kwcantrell Mar 19, 2021
caa916e
Merge branch 'master' of https://github.com/biocore/empress into tree…
kwcantrell Mar 19, 2021
f598928
fix style
kwcantrell Mar 19, 2021
5ca5809
addressed comments
kwcantrell Mar 23, 2021
89a4326
removed shear
kwcantrell Mar 23, 2021
654df69
start ui
kwcantrell Mar 24, 2021
d6aa515
finished basic shear ui
kwcantrell Mar 25, 2021
de01d93
fixed test issue
kwcantrell Mar 25, 2021
fcb6b5b
removed old comments
kwcantrell Mar 25, 2021
55f6f7e
merged master
kwcantrell Mar 25, 2021
b3acbd1
Apply suggestions from code review
kwcantrell Mar 30, 2021
263dd6a
started addressing PR suggestions
kwcantrell Mar 30, 2021
5bb8729
Merge branch 'shear-ui' of https://github.com/kwcantrell/empress into…
kwcantrell Mar 30, 2021
68d0d63
fixed style
kwcantrell Mar 30, 2021
603bf97
still addressing comments
kwcantrell Apr 1, 2021
31b5af3
fixed style
kwcantrell Apr 1, 2021
7f56e68
fix unselect all
kwcantrell Apr 1, 2021
9a9bb75
Fixed unselect all for circ layout
kwcantrell Apr 1, 2021
9dc26bc
fixed issue were tree disappears if all tips sheared
kwcantrell Apr 1, 2021
4445ebd
check point
kwcantrell Apr 1, 2021
15f81ab
fixed clade collapse
kwcantrell Apr 1, 2021
4630689
fixed style
kwcantrell Apr 1, 2021
73892fd
fixed test
kwcantrell Apr 1, 2021
3ca595e
fixed no biom error
kwcantrell Apr 2, 2021
66e5ded
checkpoint
kwcantrell Apr 6, 2021
9eb4243
performance improvemens
kwcantrell Apr 7, 2021
e3d128f
merged master
kwcantrell Apr 8, 2021
4b4d8e3
finished documenting
kwcantrell Apr 9, 2021
3d05f17
style fix
kwcantrell Apr 9, 2021
d909e83
added warning to shear
kwcantrell Apr 9, 2021
3b6d854
Major performance increase!
kwcantrell Apr 11, 2021
0803dc0
Apply suggestions from code review
kwcantrell Apr 12, 2021
cc754e9
fix style
kwcantrell Apr 12, 2021
3a2eede
Add warning message to shear panel
kwcantrell Apr 13, 2021
95392a5
starting addressing @fedarko's comments
kwcantrell May 4, 2021
45e2d49
addressed @fedarko's comments
kwcantrell May 4, 2021
3570a19
Merge branch 'master' of https://github.com/biocore/empress into shea…
kwcantrell May 4, 2021
e78ecd1
fix test
kwcantrell May 4, 2021
c95adf8
Apply suggestions from code review
kwcantrell May 17, 2021
af71569
added more @fedarko's suggestions + stle fix
kwcantrell May 17, 2021
35a2aa9
Merge branch 'master' of https://github.com/biocore/empress into shea…
kwcantrell May 28, 2021
928a2ce
address @fedarko's PR comments
kwcantrell May 28, 2021
6d4571a
Merge branch 'master' of https://github.com/biocore/empress into shea…
kwcantrell Jun 6, 2021
6074e5d
fixed collapse issue
kwcantrell Jun 10, 2021
0b081ca
Merge branch 'master' of https://github.com/biocore/empress into shea…
kwcantrell Jun 10, 2021
0bd1160
Apply suggestions from code review
kwcantrell Jun 10, 2021
d3c2a61
fixed callback for emperor selections
kwcantrell Jun 10, 2021
ac544fb
fixed style
kwcantrell Jun 10, 2021
55ca475
modified node circle text
kwcantrell Jun 10, 2021
aedb860
merged with master
kwcantrell Jun 11, 2021
90571be
disabled tabs during animation
kwcantrell Jun 11, 2021
149ecb5
fixed tests/lint issues
kwcantrell Jun 11, 2021
288a140
Apply suggestions from code review
kwcantrell Jun 29, 2021
7faa70a
modified message
kwcantrell Jun 29, 2021
cb085ba
addressed comments
kwcantrell Jun 29, 2021
8af9b93
fixed python test
kwcantrell Jun 29, 2021
c0fbd57
Merge branch 'master' of https://github.com/biocore/empress into pr50…
fedarko Jul 17, 2021
0505705
Remove extra " in side panel disabled message
fedarko Jul 17, 2021
924b938
rm another extra "
fedarko Jul 17, 2021
0bae2ce
space after "
fedarko Jul 17, 2021
953abd8
fix problem i introduced in the last commit ._.
fedarko Jul 17, 2021
8767132
MNT: RM \t chars, make e-d-*.js docs consistent
fedarko Jul 17, 2021
01d7022
DOC: Adjust tab-disabled prefix using isEmpirePlot
fedarko Jul 17, 2021
c57a5d2
DOC: Make uses of bold fonts consistent
fedarko Jul 17, 2021
00b7dee
STY: prettify
fedarko Jul 17, 2021
b664bfd
Cleaner toast msg for no-FM-b/c-shearing case
fedarko Jul 17, 2021
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
6 changes: 6 additions & 0 deletions empress/support_files/css/empress.css
Original file line number Diff line number Diff line change
Expand Up @@ -681,11 +681,17 @@ p.side-header button:hover,

/* Somewhere else in the CSS adjusts line height and justify-content,
* so we reset these here.
*
* Also, the reason for display: block is because the .control p CSS
* elsewhere causes weird problems when there are other tags (e.g.
* <span>s, like in the shearing UI) within <p> tags of class
* side-panel-notes due to the flex display.
*/
.side-panel-notes {
font-size: small;
line-height: normal !important;
justify-content: start !important;
display: block !important;
}

.indented {
Expand Down
35 changes: 34 additions & 1 deletion empress/support_files/js/biom-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ define(["underscore", "util"], function (_, util) {
this._tbl = tbl;
this._smCols = smCols;
this._sm = sm;

/**
* A set of feature IDs to ignore. This will be updated whenever
* the tree is sheared, and will contain the IDs of the features in
* the BIOM table (tips) that were removed.
* @ type {Set}
*/
this.ignorefIdx = new Set();
}

/**
Expand Down Expand Up @@ -278,7 +286,9 @@ define(["underscore", "util"], function (_, util) {
var cVal;
var addSampleFeatures = function (sIdx, cVal) {
_.each(scope._tbl[sIdx], function (fIdx) {
valueToFeatureIdxs[cVal].add(fIdx);
if (!scope.ignorefIdx.has(fIdx)) {
valueToFeatureIdxs[cVal].add(fIdx);
}
});
};
// For each sample...
Expand Down Expand Up @@ -582,6 +592,10 @@ define(["underscore", "util"], function (_, util) {
var fID2Freqs = {};
var totalSampleCount;
_.each(this._fIDs, function (fID, fIdx) {
// we dont want to consider features that have been marked as ignore
if (scope.ignorefIdx.has(fIdx)) {
return;
}
totalSampleCount = fIdx2SampleCt[fIdx];
fID2Freqs[fID] = {};
_.each(fIdx2Counts[fIdx], function (count, smValIdx) {
Expand All @@ -591,8 +605,27 @@ define(["underscore", "util"], function (_, util) {
}
});
});

return fID2Freqs;
};

/**
* Set which features to ignore. Features in this set will not be
* considered in functions such as getObsBy() or getFrequencyMap()
*
* @param {Set} nodes A set of feature ids to ignore
*/
BIOMTable.prototype.setIgnoreNodes = function (nodes) {
var scope = this;

// convert feature ids to feature indices
// [...nodes] converts nodes from Set to Array: see
// https://stackoverflow.com/a/63818423
var nodeIdx = _.map([...nodes], (fId) => {
return scope._getFeatureIndexFromID(fId);
});
this.ignorefIdx = new Set(nodeIdx);
};

return BIOMTable;
});
125 changes: 89 additions & 36 deletions empress/support_files/js/bp-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
* performance boost
*/
var eCache = [];
for (var i = 0; i < this.b_.length; i++) {
var i;
for (i = 0; i < this.b_.length; i++) {
eCache.push(2 * this.r1Cache_[i] - i - 1);
}
this.eCache_ = new Uint32Array(eCache);
Expand Down Expand Up @@ -190,6 +191,33 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
* that have the same name.
*/
this._nameToNodes = {};

/**
* @type {Array}
* @private
* Cache Parent nodes. This will help speed up a lot of methods that
* make calls to parent.
*/
this._pCache = [];
var pStack = [];
for (i = 0; i < this.b_.length - 1; i++) {
if (this.b_[i] === 1) {
if (pStack.length === 0) {
pStack.push(i);
this._pCache[i] = 0;
} else if (this.b_[i + 1] === 1) {
this._pCache[i] = pStack[pStack.length - 1];
pStack.push(i);
} else if (this.b_[i + 1] === 0) {
this._pCache[i] = pStack[pStack.length - 1];
}
} else if (this.b_[i] === 0) {
this._pCache[i] = pStack[pStack.length - 1];
if (this.b_[i + 1] === 0) {
pStack.pop();
}
}
Comment on lines +203 to +219
Copy link
Member

Choose a reason for hiding this comment

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

Should this block be moved to a helper method? Seems a bit odd that it's in the init method.

}
}

/**
Expand All @@ -204,7 +232,11 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
* testing).
*/
BPTree.prototype.getLengthStats = function () {
if (this.lengths_ !== null) {
// first check if tree only contains 1 node (length === 2 since the
// lengths array starts at index 1.)
if (this.lengths_ !== null && this.lengths_.length === 2) {
return { min: "N/A", max: "N/A", avg: "N/A" };
} else if (this.lengths_ !== null) {
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
var min = Number.POSITIVE_INFINITY,
max = Number.NEGATIVE_INFINITY,
sum = 0,
Expand Down Expand Up @@ -452,7 +484,7 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
return -1;
}

return this.enclose(i);
return this._pCache[i];
};

/**
Expand Down Expand Up @@ -702,7 +734,9 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
// find first and last preorder positions of the subtree spanned
// by the current internal node
var n = this.postorderselect(nodeKey);
if (this.isleaf(n)) {

// check for root to account for cases when all tips have been sheared
if (this.isleaf(n) && nodeKey !== this.postorder(this.root())) {
throw "Error: " + nodeKey + " is a tip!";
}
var start = this.preorder(this.fchild(n));
Expand Down Expand Up @@ -972,53 +1006,69 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
};

/**
* Returns a new BPTree object that contains just the tips (and ancestors)
* of the nodes in keepTips.
* Returns a new BPTree object that does not contain the tips in removeTips.
*
* This method was ported from iow.
* https://github.com/wasade/improved-octo-waddle/blob/0e9e75b77238acda6752f59d940620f89607ba6b/bp/_bp.pyx#L732
*
* @param {Set} keepTips The set of tip names to keep.
* @param {Set} removeTips The set of tip names to remove.
*
* @return {Object} An object containing the new tree ("tree") and two maps that
* convert the original postorder positions to the sheared
* tree postorder positions ("newToOld") and vice-versa ("oldToNew").
*/
BPTree.prototype.shear = function (keepTips) {
BPTree.prototype.shear = function (removeTips) {
fedarko marked this conversation as resolved.
Show resolved Hide resolved
// closure
var scope = this;

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

// create new bit array
var mask = [];
var mask = _.clone(this.b_);

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

// set root open/close bits
set_bits(this.root());
// remove tips
for (i of removeTips) {
node = this.postorderselect(i);
mask[node] = undefined;
mask[node + 1] = undefined;
}

// 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);
// remove internal
var nodeStack = [];
for (i = mask.length - 1; i > 0; i--) {
if (mask[i] === 0) {
// close parentheses
if (mask[i - 1] === 0) {
// close parentheses represents internal node
nodeStack.push([i, null]);
} else if (mask[i - 1] === 1) {
// close parentheses represents non-removed tip
// thus we mark it as false so it is not removed
nodeStack.push([i, false]);
} else if (mask[i - 1] === undefined) {
// close parentheses represents an internal node
// with at least one removed tip so we temporarly mark it
// as true to remove
nodeStack.push([i, true]);
}
} else if (mask[i] === 1) {
// open parentheses
node = nodeStack.pop();
if (node[1] === true) {
// remove internal node
mask[i] = undefined;
mask[node[0]] = undefined;
} else if (node[1] === false) {
// need explicitly check false since it can be null
// if node[1] is false that means it contains a tip and thus
// we need to mark its parent as false so it is not removed
nodeStack[nodeStack.length - 1][1] = false;
}

if (nodeStack[nodeStack.length - 1][1] === null) {
// if null then we set its remove status to whatever node
// was
nodeStack[nodeStack.length - 1][1] = node[1];
}
}
}
Expand All @@ -1027,14 +1077,16 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
var shearedToFull = new Map();
var fullToSheared = new Map();
var postorderPos = 1;
// create new names and lengths array
var names = [null];
var lengths = [null];
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

if (mask[i] === 0) {
names.push(this.name(i));
lengths.push(this.length(i));
Expand All @@ -1043,6 +1095,7 @@ define(["ByteArray", "underscore"], function (ByteArray, _) {
postorderPos += 1;
}
}

return {
shearedToFull: shearedToFull,
fullToSheared: fullToSheared,
Expand Down
4 changes: 3 additions & 1 deletion empress/support_files/js/canvas-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ define(["underscore", "glMatrix", "SelectedNodeMenu"], function (

// Go through all the nodes in the tree and find the node
// closest to the (x, y) point that was clicked
for (var node = 1; node <= empress._tree.size; node++) {
for (var node of empress._tree.postorderTraversal(
(includeRoot = true)
)) {
if (!empress.getNodeInfo(node, "visible")) continue;
var nodeX = empress.getX(node);
var nodeY = empress.getY(node);
Expand Down
2 changes: 2 additions & 0 deletions empress/support_files/js/drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ define(["underscore", "glMatrix", "Camera", "Colorer"], function (
* @param{Number} zoomAmount The amout to zoom in or out.
*/
Drawer.prototype.zoom = function (x, y, zoomIn, zoomAmount = this.scaleBy) {
// zoomAmount can be zero if all tips in the tree were sheared.
if (zoomAmount === 0) zoomAmount = this.scaleBy;
var zoomAt = gl.vec4.fromValues(x, y, 0, 1);
// move tree
var transVec = gl.vec3.create();
Expand Down
Loading