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

Gradient Coloring Option for Feature Metadata #484

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
61f49b2
Add custom color
kwcantrell Feb 1, 2021
1f26583
checkpoint
kwcantrell Feb 10, 2021
dd2cfe6
added gradient coloring for feature metadata
kwcantrell Feb 10, 2021
20b369a
linter
kwcantrell Feb 10, 2021
6172f36
style fix
kwcantrell Feb 10, 2021
a3a1fe4
Show warning to user
kwcantrell Feb 22, 2021
3a69861
checkpoint
kwcantrell Feb 23, 2021
ca591ba
gradient feature metadata coloring
kwcantrell Feb 23, 2021
86ef3cf
fixed style issue
kwcantrell Feb 23, 2021
f2920c5
Merge branch 'master' of https://github.com/biocore/empress into grad…
kwcantrell Feb 24, 2021
a4052df
addressed comments
kwcantrell Mar 2, 2021
84d5b4a
style fix
kwcantrell Mar 2, 2021
8836260
Apply suggestions from code review
kwcantrell Mar 2, 2021
1431e2c
Merge branch 'master' of https://github.com/biocore/empress into grad…
kwcantrell Apr 9, 2021
743a32e
fix style
kwcantrell Apr 9, 2021
a90871c
fixed continuous error
kwcantrell Apr 9, 2021
305aa47
remove try-catch
kwcantrell Apr 12, 2021
d5426f6
Apply suggestions from code review
kwcantrell May 4, 2021
bf3f5fd
Merge branch 'master' of https://github.com/biocore/empress into grad…
kwcantrell Jun 10, 2021
aba2aa7
checkpoint
kwcantrell Jun 11, 2021
942f5b0
added test/fixed warning
kwcantrell Jun 11, 2021
9bd5961
fixed docs
kwcantrell Jun 11, 2021
6033e11
abstracted Legend class
kwcantrell Jun 13, 2021
1472ee4
Apply suggestions from code review
kwcantrell Aug 3, 2021
25ac9bd
address error 1
kwcantrell Aug 26, 2021
0add7c7
fixed conflicts
kwcantrell Aug 26, 2021
8206de8
fixed color bug
kwcantrell Aug 26, 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
10 changes: 5 additions & 5 deletions empress/support_files/js/barplot-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ define([
"underscore",
"spectrum",
"Colorer",
"Legend",
"BarplotLegend",
"util",
], function ($, _, spectrum, Colorer, Legend, util) {
], function ($, _, spectrum, Colorer, BarplotLegend, util) {
/**
*
* @class BarplotLayer
Expand Down Expand Up @@ -634,14 +634,14 @@ define([
this.colorLegendDiv.classList.add("hidden");
this.colorLegendDiv.classList.add("legend");
this.colorLegendDiv.classList.add("barplot-layer-legend");
this.colorLegend = new Legend(this.colorLegendDiv);
this.colorLegend = new BarplotLegend(this.colorLegendDiv);
this.layerDiv.appendChild(this.colorLegendDiv);

this.lengthLegendDiv = document.createElement("div");
this.lengthLegendDiv.classList.add("hidden");
this.lengthLegendDiv.classList.add("legend");
this.lengthLegendDiv.classList.add("barplot-layer-legend");
this.lengthLegend = new Legend(this.lengthLegendDiv);
this.lengthLegend = new BarplotLegend(this.lengthLegendDiv);
this.layerDiv.appendChild(this.lengthLegendDiv);

// TODO: if possible, making the legend text selectable (overriding
Expand Down Expand Up @@ -757,7 +757,7 @@ define([
* effect) will be excluded from the Array. However, if all legends are
* active, the order in the Array will always be color then length.
*
* @return {Array} Array of Legend objects
* @return {Array} Array of BarplotLegend objects
*/
BarplotLayer.prototype.getLegends = function () {
var containedLegends = [this.colorLegend, this.lengthLegend];
Expand Down
35 changes: 35 additions & 0 deletions empress/support_files/js/barplot-legend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
define(["Legend"], function (Legend) {
/**
* @class SampleFeatureColorLegend
*/
function BarplotLegend(container) {
// call Legend constructor
Legend.call(this, container);

/**
* @type {String}
* Text to display at the bottom of the continuous legend when some
* values in a continuous are either missing or non-numeric.
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
*/
this.continuousMissingNonNumericWarning =
"Some value(s) in this field were missing and/or not numeric. " +
"These value(s) have been left out of the gradient, and no " +
"bar(s) have been drawn for them.";

/**
* @type {String}
* Short version of the above warning, shown for the same legends when
* exported to SVG
*/
this.continuousMissingNonNumericWarningShort =
"Missing / non-numeric value(s) omitted.";
}

// inherit Legend functions
BarplotLegend.prototype = Object.create(Legend.prototype);

// set BarplotLegend's constructor
BarplotLegend.prototype.constructor = BarplotLegend;

return BarplotLegend;
});
26 changes: 8 additions & 18 deletions empress/support_files/js/empress.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ define([
"VectorOps",
"CanvasEvents",
"BarplotPanel",
"Legend",
"SampleFeatureColorLegend",
"util",
"chroma",
"LayoutsUtil",
Expand All @@ -20,7 +20,7 @@ define([
VectorOps,
CanvasEvents,
BarplotPanel,
Legend,
SampleFeatureColorLegend,
util,
chroma,
LayoutsUtil,
Expand Down Expand Up @@ -159,24 +159,12 @@ define([
}

/**
* @type {String}
* Text to display at the bottom of the continuous legend when some
* values in a continuous are either missing or non-numeric.
*/
this._continuousMissingNonNumericWarning =
"Some value(s) in this field were missing and/or not numeric. " +
"These value(s) have been left out of the gradient, and the " +
"corresponding nodes have been set to the default color.";
/**
* @type {Legend}
* @type {SampleFeatureColorLegend}
* Legend describing the way the tree is colored.
* @private
*/
this._legend = new Legend(document.getElementById("legend-main"));
this._legend.setMissingNonNumericWarning(
"Some value(s) in this field were missing and/or not numeric. " +
"These value(s) are not included in the gradient, and the " +
"associated nodes have been left as the default color."
this._legend = new SampleFeatureColorLegend(
document.getElementById("legend-main")
);

/**
Expand Down Expand Up @@ -2514,7 +2502,7 @@ define([
'" has less than 2 unique numeric values, so it cannot be ' +
"used for continuous coloring. " +
"Using discrete coloring instead.";
util.toastMsg(msg, 5000);
util.toastMsg("Feature metadata coloring error", msg, 5000);
// assign colors to unique values
colorer = new Colorer(
color,
Expand Down Expand Up @@ -2545,6 +2533,8 @@ define([

// color tree
this._colorTree(obs, cm);

this.resizeLegend();
if (continuous) {
this._legend.addContinuousKey(cat, keyInfo);
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
} else {
fedarko marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
79 changes: 47 additions & 32 deletions empress/support_files/js/legend.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
define(["jquery", "underscore", "util"], function ($, _, util) {
/**
*
* @Abstract
* @class Legend
*
* Creates a legend within a given HTML element. (You'll need to call
Expand All @@ -11,7 +12,6 @@ define(["jquery", "underscore", "util"], function ($, _, util) {
* will be added.
*
* @return {Legend}
* @constructs Legend
*/
function Legend(container) {
/**
Expand Down Expand Up @@ -102,6 +102,25 @@ define(["jquery", "underscore", "util"], function ($, _, util) {
*/
this._minLengthVal = null;
this._maxLengthVal = null;

/**
* @type {String}
* Text to display at the bottom of the continuous legend when some
* values in a continuous are either missing or non-numeric.
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
*/
this.continuousMissingNonNumericWarning = null;

/**
* @type {String}
* Short version of the above warning, shown for the same legends when
* exported to SVG
*/
this.continuousMissingNonNumericWarningShort = null;

// make Legend an abstract class
if (this.constructor === Legend) {
throw new Error("Abstract class Legend can not be instantiated.");
}
}

/**
Expand Down Expand Up @@ -183,7 +202,20 @@ define(["jquery", "underscore", "util"], function ($, _, util) {
containerSVG.setAttribute("style", "display: block; margin: auto;");
// just kinda plop the combined SVG code into containerSVG's HTML
containerSVG.innerHTML = totalHTMLSVG;
this._container.appendChild(containerSVG);

// We need to put the svg container inside a div otherwise some unwanted
// behavior will occur when users resize the legend.
// The gradient bar's height is set to be 80% of the legend's
// height. This works for most cases howevr, some issues come up when
// the uesr resizes the legned. i.e. the height of the graident color
// bar will continuously be set to 80% of the legend's height which
// can hide the warning message(s) that appear benith the gradient.
// By putting the svg container inside a div, the gradient color bar
// will be set to 80% of the initial size of the legend and will remain
// fixed when users resize the legend.
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
var fixSizeDiv = document.createElement("div");
fixSizeDiv.appendChild(containerSVG);
this._container.appendChild(fixSizeDiv);
if (this._missingNonNumericWarningShown) {
var missingText = this.getMissingNonNumericWarning();
var warningP = document.createElement("p");
Expand Down Expand Up @@ -744,40 +776,23 @@ define(["jquery", "underscore", "util"], function ($, _, util) {
};
};

Legend.prototype.setMissingNonNumericWarning = function (
full,
short = null
) {
this.continuousMissingNonNumericWarning = full;
this.continuousMissingNonNumericWarningShort = short;
};

/**
* Returns the full and short versions of the continuous missing
* non-numeric warning messages.
*
* @return {Object} The object is formated as follows
* {
* full: messageString,
* short: messageString
* }
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
*/
Legend.prototype.getMissingNonNumericWarning = function () {
var missingText = {
full: Legend.CONTINUOUS_MISSING_NON_NUMERIC_WARNING,
short: Legend.CONTINUOUS_MISSING_NON_NUMERIC_WARNING_SHORT,
return {
full: this.continuousMissingNonNumericWarning,
short: this.continuousMissingNonNumericWarningShort,
};
if (this.hasOwnProperty("continuousMissingNonNumericWarning")) {
missingText.full = this.continuousMissingNonNumericWarning;
}
if (this.hasOwnProperty("continuousMissingNonNumericWarningShort")) {
missingText.short = this.continuousMissingNonNumericWarningShort;
}
return missingText;
};

// Shown at the bottom of continuous legends in the page when some values
// in a continuous field can't be represented on a gradient
Legend.CONTINUOUS_MISSING_NON_NUMERIC_WARNING =
"Some value(s) in this field were missing and/or not numeric. " +
"These value(s) have been left out of the gradient, and no bar(s) " +
"have been drawn for them.";

// Short version of the above warning, shown for the same legends when
// exported to SVG
Legend.CONTINUOUS_MISSING_NON_NUMERIC_WARNING_SHORT =
"Missing / non-numeric value(s) omitted.";

// Various SVG attributes stored here since they're used every time the
// export function is called
Legend.LINE_HEIGHT = 54;
Expand Down
36 changes: 36 additions & 0 deletions empress/support_files/js/sample-feature-color-legend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
define(["Legend"], function (Legend) {
/**
* @class SampleFeatureColorLegend
*/
function SampleFeatureColorLegend(container) {
// call Legend constructor
Legend.call(this, container);

/**
* @type {String}
* Text to display at the bottom of the continuous legend when some
* values in a continuous are either missing or non-numeric.
*/
this.continuousMissingNonNumericWarning =
"Some value(s) in this field were missing and/or not numeric. " +
"These value(s) have been left out of the gradient, and the " +
"corresponding nodes have been set to the default color.";

/**
* @type {String}
* Short version of the above warning, shown for the same legends when
* exported to SVG
*/
this.continuousMissingNonNumericWarningShort =
"Missing / non-numeric value(s)' associated nodes left as " +
"default color.";
}

// inherit Legend functions
SampleFeatureColorLegend.prototype = Object.create(Legend.prototype);

// set SampleFeatureColorLegend's constructor
SampleFeatureColorLegend.prototype.constructor = SampleFeatureColorLegend;

return SampleFeatureColorLegend;
});
4 changes: 3 additions & 1 deletion empress/support_files/templates/empress-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ <h3 id="menu-sm-header">Sample Presence Information</h3>
'util' : './js/util',
'LayoutsUtil': './js/layouts-util',
'ExportUtil': './js/export-util',
'TreeController': './js/tree-controller'
'TreeController': './js/tree-controller',
'SampleFeatureColorLegend': './js/sample-feature-color-legend',
'BarplotLegend': './js/barplot-legend',
}
});

Expand Down
2 changes: 2 additions & 0 deletions tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ <h3 id="menu-sm-header">Sample Presence Information</h3>
'LayoutsUtil' : './support_files/js/layouts-util',
'ExportUtil' : './support_files/js/export-util',
'TreeController' : './support_files/js/tree-controller',
'SampleFeatureColorLegend': './support_files/js/sample-feature-color-legend',
'BarplotLegend': './support_files/js/barplot-legend',

/* test utility code */
'UtilitiesForTesting' : './../tests/utilities-for-testing',
Expand Down
6 changes: 3 additions & 3 deletions tests/test-animation-panel-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require([
"BPTree",
"Empress",
"BiomTable",
"Legend",
"SampleFeatureColorLegend",
"util",
"Colorer",
], function (
Expand All @@ -15,7 +15,7 @@ require([
BPTree,
Empress,
BiomTable,
Legend,
SampleFeatureColorLegend,
util,
Colorer
) {
Expand Down Expand Up @@ -96,7 +96,7 @@ require([
var empress = new Empress({ size: 0 }, biom, [], [], {}, {}, null);
var animator = new Animator(
empress,
new Legend(
new SampleFeatureColorLegend(
document.createElement("div"),
document.createElement("div"),
document.createElement("div")
Expand Down
16 changes: 11 additions & 5 deletions tests/test-empress.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,12 @@ require([
var resultProperties = util.naturalSort(Object.keys(cm));
deepEqual(resultProperties, properties);

kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
deepEqual(cm.gradientID, "Gradient-1");
deepEqual(cm.maxValStr, "2");
deepEqual(cm.midValStr, "1.5");
deepEqual(cm.minValStr, "1");
deepEqual(cm.missingNonNumerics, false);

// make sure nodes were assigned correct color
var node;
var group1 = new Set([2, 3, 4]);
Expand Down Expand Up @@ -445,18 +451,18 @@ require([
}
});

test("Test colorByFeatureMetadata, continuous no numberic values", function () {
// hack to add a metadata column with no numberic data
test("Test colorByFeatureMetadata, continuous: failure due to no numberic values", function () {
kwcantrell marked this conversation as resolved.
Show resolved Hide resolved
// hack to add a metadata column with no numeric data
this.empress._featureMetadataColumns = ["f1", "f2", "f3"];
this.empress._tipMetadata = {
1: ["2", "2", "n1"],
2: ["1", "2", "n2"],
3: ["1", "2", "n3"],
6: ["2", "2", "n4"],
};
var faileFunctionCalled = false;
var failedFunctionCalled = false;
var failedFunction = () => {
faileFunctionCalled = true;
failedFunctionCalled = true;
};
var cm = this.empress.colorByFeatureMetadata(
"f3",
Expand All @@ -466,7 +472,7 @@ require([
true,
failedFunction
);
ok(faileFunctionCalled, "continousFailedFunc was not called.");
ok(failedFunctionCalled, "continousFailedFunc was called.");
});

test("Test _projectObservations, all tips in obs", function () {
Expand Down
Loading