aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2017-02-24 17:14:46 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2017-02-24 17:25:09 -0800
commit65bdf9d6588ba9b7c3b917d0c556c0c2e6332e45 (patch)
tree2b51f6d28318ce9eee70b88c566d1246f91c3d68
parent736d1551d47c61c93b25943334d132aa0f06b2c2 (diff)
Refine the UI of health pills.
Changed colors used to render health pills. Added a drop shadow with an SVG gaussian filter (CSS does not suffice) to make the light gray (for the positive values category) stand out. Rewrote rendering logic to use a discrete gradient for rendering health pill colors to allow for the filter. Change: 148522653
-rw-r--r--tensorflow/tensorboard/components/tf_graph/tf-graph-scene.html24
-rw-r--r--tensorflow/tensorboard/components/tf_graph/tf-graph.html2
-rw-r--r--tensorflow/tensorboard/components/tf_graph_common/lib/scene/scene.ts96
3 files changed, 74 insertions, 48 deletions
diff --git a/tensorflow/tensorboard/components/tf_graph/tf-graph-scene.html b/tensorflow/tensorboard/components/tf_graph/tf-graph-scene.html
index 480104519b..c837e6c684 100644
--- a/tensorflow/tensorboard/components/tf_graph/tf-graph-scene.html
+++ b/tensorflow/tensorboard/components/tf_graph/tf-graph-scene.html
@@ -479,6 +479,15 @@ limitations under the License.
display: none;
}
+::content .health-pill {
+ filter: url(#health-pill-shadow);
+}
+
+::content .health-pill rect {
+ rx: 3;
+ ry: 3;
+}
+
.titleContainer {
position: relative;
top: 20px;
@@ -581,6 +590,18 @@ limitations under the License.
<pattern id="ellipseHatch" patternTransform="rotate(45 0 0)" width="2" height="2" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="2" style="stroke-width: 1"/>
</pattern>
+
+ <!-- A shadow for health pills. -->
+ <filter id="health-pill-shadow" x="-40%" y="-40%" width="180%" height="180%">
+ <feGaussianBlur in="SourceAlpha" stdDeviation="0.8"/>
+ <feOffset dx="0" dy="0" result="offsetblur"/>
+ <feFlood flood-color="#000000"/>
+ <feComposite in2="offsetblur" operator="in"/>
+ <feMerge>
+ <feMergeNode/>
+ <feMergeNode in="SourceGraphic"/>
+ </feMerge>
+ </filter>
</defs>
<!-- Make a large rectangle that fills the svg space so that
zoom events get captured on safari -->
@@ -895,7 +916,8 @@ Polymer({
return this._edgeGroupIndex[e];
},
_updateHealthPills: function(nodeNamesToHealthPills, healthPillStepIndex) {
- tf.graph.scene.addHealthPills(this.$.svg, nodeNamesToHealthPills, healthPillStepIndex);
+ tf.graph.scene.addHealthPills(
+ this.$.svg, nodeNamesToHealthPills, healthPillStepIndex);
},
/**
* Update node and annotation node of the given name.
diff --git a/tensorflow/tensorboard/components/tf_graph/tf-graph.html b/tensorflow/tensorboard/components/tf_graph/tf-graph.html
index 7e4fe9e6e7..8792f475c4 100644
--- a/tensorflow/tensorboard/components/tf_graph/tf-graph.html
+++ b/tensorflow/tensorboard/components/tf_graph/tf-graph.html
@@ -61,7 +61,7 @@ paper-button {
<tf-graph-scene id="scene" class="auto"
render-hierarchy="[[renderHierarchy]]"
highlighted-node="[[_getVisible(highlightedNode)]]"
- selected-node="[[selectedNode]]"
+ selected-node="{{selectedNode}}"
color-by="[[colorBy]]"
progress="[[progress]]"
node-names-to-health-pills="[[nodeNamesToHealthPills]]"
diff --git a/tensorflow/tensorboard/components/tf_graph_common/lib/scene/scene.ts b/tensorflow/tensorboard/components/tf_graph_common/lib/scene/scene.ts
index 182936dcf2..2b5e6c8b29 100644
--- a/tensorflow/tensorboard/components/tf_graph_common/lib/scene/scene.ts
+++ b/tensorflow/tensorboard/components/tf_graph_common/lib/scene/scene.ts
@@ -103,23 +103,23 @@ module tf.graph.scene {
label: 'NaN',
},
{
- background_color: '#FFFF00',
+ background_color: '#FF8D00',
label: '- ∞',
},
{
- background_color: '#A8A8A8',
+ background_color: '#EAEAEA',
label: '-',
},
{
- background_color: '#D8DBE2',
+ background_color: '#A5A5A5',
label: '0',
},
{
- background_color: '#424242',
+ background_color: '#262626',
label: '+',
},
{
- background_color: '#FFA500',
+ background_color: '#003ED4',
label: '+ ∞',
},
];
@@ -512,9 +512,7 @@ function _addHealthPill(
nodeGroupElement: SVGElement, healthPill: HealthPill,
nodeInfo: render.RenderGroupNodeInfo) {
// Check if text already exists at location.
- d3.select(nodeGroupElement.parentNode)
- .selectAll('.health-pill-group')
- .remove();
+ d3.select(nodeGroupElement.parentNode).selectAll('.health-pill').remove();
if (!nodeInfo || !healthPill) {
return;
@@ -525,6 +523,7 @@ function _addHealthPill(
// For now, we only visualize the 6 values that summarize counts of tensor
// elements of various categories: -Inf, negative, 0, positive, Inf, and NaN.
let lastHealthPillOverview = lastHealthPillData.slice(2, 8);
+ let totalCount = lastHealthPillData[1];
let healthPillWidth = 60;
let healthPillHeight = 10;
@@ -534,66 +533,71 @@ function _addHealthPill(
healthPillHeight /= 2;
}
- let healthPillSvg = document.createElementNS(svgNamespace, 'svg');
- healthPillSvg.classList.add('health-pill-group');
- healthPillSvg.setAttribute('width', String(healthPillWidth));
- healthPillSvg.setAttribute('height', String(healthPillHeight));
-
- let svgDefs = document.createElementNS(svgNamespace, 'defs');
- healthPillSvg.appendChild(svgDefs);
- let clipPath = document.createElementNS(svgNamespace, 'clipPath');
- clipPath.setAttribute('id', 'health-pill-clip-path');
- svgDefs.appendChild(clipPath);
- let clipRect = document.createElementNS(svgNamespace, 'rect');
- clipRect.setAttribute('height', String(healthPillHeight));
- clipRect.setAttribute('width', String(healthPillWidth));
- clipRect.setAttribute('rx', '2');
- clipRect.setAttribute('ry', '2');
- clipPath.appendChild(clipRect);
-
- let rectGroup = document.createElementNS(svgNamespace, 'g');
- rectGroup.setAttribute('clip-path', 'url(#health-pill-clip-path)');
- healthPillSvg.appendChild(rectGroup);
- let totalCount = lastHealthPillData[1];
- // Create 1 rectangle for each category.
- let totalCountSoFar = 0;
- let totalWidthDividedByTotalCount = healthPillWidth / totalCount;
+ let healthPillGroup = document.createElementNS(svgNamespace, 'g');
+ healthPillGroup.classList.add('health-pill');
+
+ // Define the gradient for the health pill.
+ let healthPillDefs = document.createElementNS(svgNamespace, 'defs');
+ healthPillGroup.appendChild(healthPillDefs);
+ let healthPillGradient =
+ document.createElementNS(svgNamespace, 'linearGradient');
+ const healthPillGradientId = 'health-pill-gradient';
+ healthPillGradient.setAttribute('id', healthPillGradientId);
let titleOnHoverTextEntries = [];
+ let cumulativeCount = 0;
+ let previousOffset = '0%';
for (let i = 0; i < lastHealthPillOverview.length; i++) {
if (!lastHealthPillOverview[i]) {
- // Do not render empty rectangles.
+ // Exclude empty categories.
continue;
}
- let rect = document.createElementNS(svgNamespace, 'rect');
- rect.setAttribute('height', String(healthPillHeight));
- let rectWidth = totalWidthDividedByTotalCount * lastHealthPillOverview[i];
- rect.setAttribute('width', String(rectWidth));
- let rectX = totalWidthDividedByTotalCount * totalCountSoFar;
- rect.setAttribute('x', String(rectX));
- rect.setAttribute('fill', healthPillEntries[i].background_color);
- totalCountSoFar += lastHealthPillOverview[i];
- rectGroup.appendChild(rect);
+ cumulativeCount += lastHealthPillOverview[i];
+
+ // Create a color interval using 2 stop elements.
+ let stopElement0 = document.createElementNS(svgNamespace, 'stop');
+ stopElement0.setAttribute('offset', previousOffset);
+ stopElement0.setAttribute(
+ 'stop-color', healthPillEntries[i].background_color);
+ healthPillGradient.appendChild(stopElement0);
+
+ let stopElement1 = document.createElementNS(svgNamespace, 'stop');
+ let percent = (cumulativeCount * 100 / totalCount) + '%';
+ stopElement1.setAttribute('offset', percent);
+ stopElement1.setAttribute(
+ 'stop-color', healthPillEntries[i].background_color);
+ healthPillGradient.appendChild(stopElement1);
+ previousOffset = percent;
// Include this number in the title that appears on hover.
titleOnHoverTextEntries.push(
healthPillEntries[i].label + ': ' + lastHealthPillOverview[i]);
}
+ healthPillDefs.appendChild(healthPillGradient);
+
+ // Create the rectangle for the health pill.
+ let rect = document.createElementNS(svgNamespace, 'rect');
+ rect.setAttribute('fill', 'url(#' + healthPillGradientId + ')');
+ rect.setAttribute('width', String(healthPillWidth));
+ rect.setAttribute('height', String(healthPillHeight));
+ healthPillGroup.appendChild(rect);
// Show a title with specific counts on hover.
let titleSvg = document.createElementNS(svgNamespace, 'title');
titleSvg.textContent = titleOnHoverTextEntries.join(', ');
- healthPillSvg.appendChild(titleSvg);
+ healthPillGroup.appendChild(titleSvg);
// Center this health pill just right above the node for the op.
let healthPillX = nodeInfo.x - healthPillWidth / 2;
- healthPillSvg.setAttribute('x', String(healthPillX));
let healthPillY = nodeInfo.y - healthPillHeight - nodeInfo.height / 2 - 2;
if (nodeInfo.labelOffset < 0) {
// The label is positioned above the node. Do not occlude the label.
healthPillY += nodeInfo.labelOffset;
}
- healthPillSvg.setAttribute('y', String(healthPillY));
- Polymer.dom(nodeGroupElement.parentNode).appendChild(healthPillSvg);
+
+ healthPillGroup.setAttribute(
+ 'transform', 'translate(' + healthPillX + ', ' + healthPillY + ')');
+
+ Polymer.dom(nodeGroupElement.parentNode).appendChild(healthPillGroup);
}
/**