Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 30 additions & 2 deletions tensorboard/plugins/graph/tf_graph_common/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,34 @@ export function getLabelForEdge(metaedge: Metaedge,
getLabelForBaseEdge(metaedge.baseEdgeList[0], renderInfo);
}

/**
* Computes the index into a set of points that constitute a path for which the
* distance along the path from the initial point is as large as possible
* without exceeding the length. This function was introduced after the
* native getPathSegAtLength method got deprecated by SVG 2.
* @param points Array of path control points. A point has x and y properties.
* Must be of length at least 2.
* @param length The length (float).
* @param lineFunc A function that takes points and returns the "d" attribute
* of a path made from connecting the points.
* @return The index into the points array.
*/
function getPathSegmentIndexAtLength(
points: render.Point[],
length: number,
lineFunc: (points: render.Point[]) => string): number {
const path = document.createElementNS(tf.graph.scene.SVG_NAMESPACE, 'path');
for (let i = 1; i < points.length; i++) {
path.setAttribute("d", lineFunc(points.slice(0, i)));
if (path.getTotalLength() > length) {
// This many points has already exceeded the length.
return i - 1;
}
}
// The entire path is shorter than the specified length.
return points.length - 1;
}

/**
* Shortens the path enought such that the tip of the start/end marker will
* point to the start/end of the path. The marker can be of arbitrary size.
Expand Down Expand Up @@ -183,7 +211,7 @@ function adjustPathPointsForMarker(points: render.Point[],
const point = pathNode.getPointAtLength(length);
// Figure out how many segments of the path we need to remove in order
// to shorten the path.
const segIndex = pathNode.getPathSegAtLength(length);
const segIndex = getPathSegmentIndexAtLength(points, length, lineFunc);
// Update the very first segment.
points[segIndex - 1] = {x: point.x, y: point.y};
// Ignore every point before segIndex - 1.
Expand All @@ -197,7 +225,7 @@ function adjustPathPointsForMarker(points: render.Point[],
const point = pathNode.getPointAtLength(length);
// Figure out how many segments of the path we need to remove in order
// to shorten the path.
const segIndex = pathNode.getPathSegAtLength(length);
const segIndex = getPathSegmentIndexAtLength(points, length, lineFunc);
// Update the very last segment.
points[segIndex] = {x: point.x, y: point.y};
// Ignore every point after segIndex.
Expand Down
18 changes: 9 additions & 9 deletions tensorboard/plugins/graph/tf_graph_common/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
module tf.graph.scene {
const svgNamespace = 'http://www.w3.org/2000/svg';
export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';

/** Enums element class of objects in the scene */
export let Class = {
Expand Down Expand Up @@ -677,14 +677,14 @@ function _addHealthPill(
healthPillHeight /= 2;
}

let healthPillGroup = document.createElementNS(svgNamespace, 'g');
let healthPillGroup = document.createElementNS(SVG_NAMESPACE, 'g');
healthPillGroup.classList.add('health-pill');

// Define the gradient for the health pill.
let healthPillDefs = document.createElementNS(svgNamespace, 'defs');
let healthPillDefs = document.createElementNS(SVG_NAMESPACE, 'defs');
healthPillGroup.appendChild(healthPillDefs);
let healthPillGradient =
document.createElementNS(svgNamespace, 'linearGradient');
document.createElementNS(SVG_NAMESPACE, 'linearGradient');

// Every element in a web page must have a unique ID.
const healthPillGradientId = 'health-pill-gradient-' + healthPillId;
Expand All @@ -700,13 +700,13 @@ function _addHealthPill(
cumulativeCount += lastHealthPillElementsBreakdown[i];

// Create a color interval using 2 stop elements.
let stopElement0 = document.createElementNS(svgNamespace, 'stop');
let stopElement0 = document.createElementNS(SVG_NAMESPACE, 'stop');
stopElement0.setAttribute('offset', previousOffset);
stopElement0.setAttribute(
'stop-color', healthPillEntries[i].background_color);
healthPillGradient.appendChild(stopElement0);

let stopElement1 = document.createElementNS(svgNamespace, 'stop');
let stopElement1 = document.createElementNS(SVG_NAMESPACE, 'stop');
let percent = (cumulativeCount * 100 / totalCount) + '%';
stopElement1.setAttribute('offset', percent);
stopElement1.setAttribute(
Expand All @@ -717,14 +717,14 @@ function _addHealthPill(
healthPillDefs.appendChild(healthPillGradient);

// Create the rectangle for the health pill.
let rect = document.createElementNS(svgNamespace, 'rect');
let rect = document.createElementNS(SVG_NAMESPACE, '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');
let titleSvg = document.createElementNS(SVG_NAMESPACE, 'title');
titleSvg.textContent = _getHealthPillTextContent(
healthPill, totalCount, lastHealthPillElementsBreakdown, numericStats);
healthPillGroup.appendChild(titleSvg);
Expand Down Expand Up @@ -761,7 +761,7 @@ function _addHealthPill(
}
}

let statsSvg = document.createElementNS(svgNamespace, 'text');
let statsSvg = document.createElementNS(SVG_NAMESPACE, 'text');
const minString =
humanizeHealthPillStat(numericStats.min, shouldRoundOnesDigit);
const maxString =
Expand Down