function addNodes()

in tensorboard/plugins/graph/tf_graph_common/hierarchy.ts [651:755]


function addNodes(h: Hierarchy, graph: SlimGraph) {
  // Maps the op of a node to names of nodes that have the op. Used to populate
  // the libraryFunctions field of the hierarchy.
  const opToNode = {};
  _.each(graph.nodes, (node, nodeName) => {
    let path = getHierarchicalPath(node.name);
    let parent: Metanode = h.root;
    parent.depth = Math.max(path.length, parent.depth);
    // Track which nodes are associated with which ops.
    if (!opToNode[node.op]) {
      opToNode[node.op] = [];
    }
    opToNode[node.op].push(node);
    // Create parent metanodes for each depth. For example if the node name
    // is 'a/b/c', then create metanodes 'a' and 'a/b', where 'a/b' is a child
    // of a.
    for (let i = 0; i < path.length; i++) {
      parent.depth = Math.max(parent.depth, path.length - i);
      parent.cardinality += node.cardinality;
      parent.opHistogram[node.op] = (parent.opHistogram[node.op] || 0) + 1;
      if (node.device != null) {
        parent.deviceHistogram[node.device] =
          (parent.deviceHistogram[node.device] || 0) + 1;
      }
      if (node.xlaCluster != null) {
        parent.xlaClusterHistogram[node.xlaCluster] =
          (parent.xlaClusterHistogram[node.xlaCluster] || 0) + 1;
      }
      // Increment parents appropriate compatibility count
      if (node.compatible) {
        parent.compatibilityHistogram.compatible =
          (parent.compatibilityHistogram.compatible || 0) + 1;
      } else {
        parent.compatibilityHistogram.incompatible =
          (parent.compatibilityHistogram.incompatible || 0) + 1;
      }
      // Increment capability counts for in and out embeddings
      _.each(node.inEmbeddings, (inNode) => {
        if (inNode.compatible) {
          parent.compatibilityHistogram.compatible =
            (parent.compatibilityHistogram.compatible || 0) + 1;
        } else {
          parent.compatibilityHistogram.incompatible =
            (parent.compatibilityHistogram.incompatible || 0) + 1;
        }
      });
      _.each(node.outEmbeddings, (outNode) => {
        if (outNode.compatible) {
          parent.compatibilityHistogram.compatible =
            (parent.compatibilityHistogram.compatible || 0) + 1;
        } else {
          parent.compatibilityHistogram.incompatible =
            (parent.compatibilityHistogram.incompatible || 0) + 1;
        }
      });
      if (i === path.length - 1) {
        break;
      }
      let name = path[i];
      let child = <Metanode>h.node(name);
      if (!child) {
        child = createMetanode(name, h.graphOptions);
        child.parentNode = parent;
        h.setNode(name, child);
        parent.metagraph.setNode(name, child);
        if (
          name.indexOf(tf_graph.FUNCTION_LIBRARY_NODE_PREFIX) === 0 &&
          parent.name === tf_graph.ROOT_NAME
        ) {
          // This metanode represents a function in the Library. We later copy
          // its contents to dynamically inject function data into the graph
          // when the subhierarchy of a metanode is built (upon its expansion).
          const functionName = name.substring(
            tf_graph.FUNCTION_LIBRARY_NODE_PREFIX.length
          );
          // For now, remember the metanode that represents the function with
          // this name.
          if (!opToNode[functionName]) {
            opToNode[functionName] = [];
          }
          h.libraryFunctions[functionName] = {
            node: child,
            usages: opToNode[functionName],
          };
          child.associatedFunction = functionName;
        }
      }
      parent = child;
    }
    // Assuming node name is 'a/b/c', assign the OpNode as a child of the
    // metanode 'a/b'.
    h.setNode(node.name, node);
    node.parentNode = parent;
    parent.metagraph.setNode(node.name, node);
    // Add each of the in-embeddings and out-embeddings in the hierarchy.
    _.each(node.inEmbeddings, function (embedding) {
      h.setNode(embedding.name, embedding);
      embedding.parentNode = node;
    });
    _.each(node.outEmbeddings, function (embedding) {
      h.setNode(embedding.name, embedding);
      embedding.parentNode = node;
    });
  });
}