diff options
Diffstat (limited to 'tensorflow/tensorboard/components/tf-graph/tf-graph.html')
-rw-r--r-- | tensorflow/tensorboard/components/tf-graph/tf-graph.html | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/tensorflow/tensorboard/components/tf-graph/tf-graph.html b/tensorflow/tensorboard/components/tf-graph/tf-graph.html new file mode 100644 index 0000000000..905d96e237 --- /dev/null +++ b/tensorflow/tensorboard/components/tf-graph/tf-graph.html @@ -0,0 +1,221 @@ +<link rel="import" href="../../bower_components/polymer/polymer.html"> +<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../../bower_components/iron-icons/iron-icons.html"> +<link rel="import" href="../../bower_components/paper-button/paper-button.html"> +<link rel="import" href="../../bower_components/paper-input/paper-input.html"> +<link rel="import" href="../../bower_components/paper-toggle-button/paper-toggle-button.html"> +<link rel="import" href="../tf-graph-common/tf-graph-common.html"> +<link rel="import" href="tf-graph-scene.html"> +<link rel="import" href="tf-graph-params.html"> +<dom-module id="tf-graph"> +<template> +<style> +.container { + width: 100%; + height: 100%; +} + +.vertical { + width:100%; + height:100%; + @apply(--layout-vertical); +} + +.auto { + @apply(--layout-flex-auto); + @apply(--layout-vertical); +} + +h2 { + text-align: center; +} + +paper-button { + text-transform: none; +} +</style> +<div class="container"> + <tf-graph-params id="graphParams"></tf-graph-params> + <div class="vertical"> + <h2>[[title]]</h2> + <tf-graph-scene id="scene" class="auto" + graph-hierarchy="[[_renderHierarchy]]" + highlighted-node="[[_getVisible(highlightedNode)]]" + selected-node="[[selectedNode]]" + color-by="[[colorBy]]" + name="[[graphName]]" + progress="[[progress]]" + ></tf-graph-scene> + </div> +</div> +</template> +</dom-module> + +<script> +Polymer({ + + is: 'tf-graph', + + properties: { + graphHierarchy: { + type: Object, + notify: true, + observer: '_graphChanged' + }, + title: String, + selectedNode: { + type: String, + notify: true, + }, + highlightedNode: { + type: String, + notify: true + }, + /** What to color the nodes by (compute time, memory, device etc.) */ + colorBy: String, + colorByParams: { + type: Object, + notify: true, + readOnly: true, // Produces and doesn't consume. + }, + // internal properties + _graphParams: { + type: Object, + value: function() { + return this.$.graphParams; + } + }, + _renderDepth: { + type: Number, + value: 1 + }, + _renderHierarchy: { + type: Object, + readOnly: true, + notify: true, + computed: '_buildRenderHierarchy(graphHierarchy, _graphParams)' + }, + _allowGraphSelect: { + type: Boolean, + value: true + } + }, + _buildRenderHierarchy: function(graphHierarchy, params) { + return tf.time('new tf.graph.render.Hierarchy', function() { + if (graphHierarchy.root.type !== tf.graph.NodeType.META) { + // root must be metanode but sometimes Polymer's dom-if has not + // remove tf-graph element yet in <tf-node-info> + // and thus mistakenly pass non-metanode to this module. + return; + } + var renderGraph = new tf.graph.render.RenderGraphInformation( + graphHierarchy, params); + // Producing the 'color by' parameters to be consumed + // by the tf-graph-controls panel. It contains information about the + // min and max values and their respective colors, as well as list + // of devices with their respective colors. + + function getColorParamsFromScale(scale) { + return { + minValue: scale.domain()[0], + maxValue: scale.domain()[1], + startColor: scale.range()[0], + endColor: scale.range()[1] + }; + } + + this._setColorByParams({ + compute_time: getColorParamsFromScale(renderGraph.computeTimeScale), + memory: getColorParamsFromScale(renderGraph.memoryUsageScale), + device: _.map(renderGraph.deviceColorMap.domain(), + function(deviceName) { + return { + device: deviceName, + color: renderGraph.deviceColorMap(deviceName) + }; + }) + }); + return renderGraph; + }.bind(this)); + }, + _getVisible: function(name) { + if (!name) { + return name; + } + return this._renderHierarchy.getNearestVisibleAncestor(name); + }, + listeners: { + 'graph-select': '_graphSelected', + 'disable-click': '_disableClick', + 'enable-click': '_enableClick', + // Nodes + 'node-toggle-expand': '_nodeToggleExpand', + 'node-select': '_nodeSelected', + 'node-highlight': '_nodeHighlighted', + 'node-unhighlight': '_nodeUnhighlighted', + + // Annotations + + /* Note: currently highlighting/selecting annotation node has the same + * behavior as highlighting/selecting actual node so we point to the same + * set of event listeners. However, we might redesign this to be a bit + * different. + */ + 'annotation-select': '_nodeSelected', + 'annotation-highlight': '_nodeHighlighted', + 'annotation-unhighlight': '_nodeUnhighlighted', + }, + _graphChanged: function() { + // When a new graph is loaded, fire this event so that there is no + // info-card being displayed for the previously-loaded graph. + this.fire('graph-select'); + }, + _graphSelected: function(event) { + // Graph selection is not allowed during an active zoom event, as the + // click seen during a zoom/pan is part of the zooming and does not + // indicate a user desire to click on a specific section of the graph. + if (this._allowGraphSelect) { + this.set('selectedNode', null); + } + // Reset this variable as a bug in d3 zoom behavior can cause zoomend + // callback not to be called if a right-click happens during a zoom event. + this._allowGraphSelect = true; + }, + _disableClick: function(event) { + this._allowGraphSelect = false; + }, + _enableClick: function(event) { + this._allowGraphSelect = true; + }, + _nodeSelected: function(event) { + if (this._allowGraphSelect) { + this.set('selectedNode', event.detail.name); + } + // Reset this variable as a bug in d3 zoom behavior can cause zoomend + // callback not to be called if a right-click happens during a zoom event. + this._allowGraphSelect = true; + }, + _nodeHighlighted: function(event) { + this.set('highlightedNode', event.detail.name); + }, + _nodeUnhighlighted: function(event) { + this.set('highlightedNode', null); + }, + _nodeToggleExpand: function(event) { + var nodeName = event.detail.name; + var renderNode = this._renderHierarchy.getRenderNodeByName(nodeName); + // Op nodes are not expandable. + if (renderNode.node.type === tf.graph.NodeType.OP) { + return; + } + this._renderHierarchy.buildSubhierarchy(nodeName); + renderNode.expanded = !renderNode.expanded; + this.querySelector('#scene').setNodeExpanded(renderNode); + // Also select the expanded node. + this._nodeSelected(event); + }, + not: function(x) { + return !x; + } +}); +</script> |