code: def analyse_model(model_pb):  # noqa: C901
      try:
          from paddle.framework import core
      except Exception:
          print(
              "Paddlepaddle is required to use add_graph interface.\n\
                Please refer to \
                https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/linux-pip.html\
                to install paddlepaddle."
          )
  
      AttrType = core.AttrType
      attr_type_name = {
          AttrType.INT: "INT",
          AttrType.INTS: "INTS",
          AttrType.LONG: "LONG",
          AttrType.LONGS: "LONGS",
          AttrType.FLOAT: "FLOAT",
          AttrType.FLOATS: "FLOATS",
          AttrType.STRING: "STRING",
          AttrType.STRINGS: "STRINGS",
          AttrType.BOOL: "BOOL",
          AttrType.BOOLS: "BOOLS",
          AttrType.BLOCK: "BLOCK",
          AttrType.BLOCKS: "BLOCKS",
      }
      ProgramDesc = core.ProgramDesc
      from paddle.utils.unique_name import generate
  
      program_desc = ProgramDesc(model_pb)
      all_ops = {}
      all_vars = {}
      all_edges = {}
      op_inputvars_dict = collections.defaultdict(list)
      op_outputvars_dict = collections.defaultdict(list)
      for i in range(program_desc.num_blocks()):
          if i != 0:  # We do not show sub block for clarity now
              continue
          block_desc = program_desc.block(i)
          # vars info
          for var_desc in block_desc.all_vars():
              try:
                  var_name = var_desc.name()
                  all_vars[var_name] = {}
                  all_vars[var_name]["name"] = var_name
                  all_vars[var_name]["shape"] = var_desc.shape()
                  all_vars[var_name]["type"] = str(var_desc.type())
                  all_vars[var_name]["dtype"] = str(var_desc.dtype())
                  all_vars[var_name]["value"] = []
                  all_vars[var_name][
                      "persistable"
                  ] = var_desc.persistable()
                  attr_dict = {}
                  for attr_name in var_desc.attr_names():
                      attr_dict[attr_name] = var_desc.attr(attr_name)
                  all_vars[var_name]["attrs"] = attr_dict
                  all_vars[var_name]["from_node"] = ""
                  all_vars[var_name]["to_nodes"] = []
  
              except Exception:
                  # feed, fetch var
                  var_name = var_desc.name()
                  all_vars[var_name] = {}
                  all_vars[var_name]["name"] = var_name
                  all_vars[var_name]["shape"] = ""
                  all_vars[var_name]["type"] = str(var_desc.type())
                  all_vars[var_name]["dtype"] = ""
                  all_vars[var_name]["value"] = []
                  all_vars[var_name][
                      "persistable"
                  ] = var_desc.persistable()
                  attr_dict = {}
                  for attr_name in var_desc.attr_names():
                      attr_dict[attr_name] = var_desc.attr(attr_name)
                  all_vars[var_name]["attrs"] = attr_dict
                  all_vars[var_name]["from_node"] = ""
                  all_vars[var_name]["to_nodes"] = []
  
      for i in range(program_desc.num_blocks()):
          if i != 0:  # We do not show sub block for clarity now
              continue
          block_desc = program_desc.block(i)
          # ops info
          for j in range(block_desc.op_size()):
              op_desc = block_desc.op(j)
              op_name = op_desc.attr("op_namescope") + generate(
                  str(op_desc.type())
              )
              all_ops[op_name] = {}
              all_ops[op_name]["name"] = op_name
              all_ops[op_name]["show_name"] = re.sub(
                  r"\[(\w|\.)*\]", "", op_name
              )
              all_ops[op_name]["type"] = str(op_desc.type())
              all_ops[op_name]["input_vars"] = {}
              all_ops[op_name]["is_leaf_node"] = True
              for input_name, variable_list in op_desc.inputs().items():
                  all_ops[op_name]["input_vars"][
                      input_name
                  ] = variable_list
                  op_inputvars_dict[op_name].extend(variable_list)
                  # fill var 'to_nodes'
                  for variable_name in variable_list:
                      all_vars[variable_name]["to_nodes"].append(
                          op_name
                      )
              all_ops[op_name]["output_vars"] = {}
              for (
                  output_name,
                  variable_list,
              ) in op_desc.outputs().items():
                  all_ops[op_name]["output_vars"][
                      output_name
                  ] = variable_list
                  op_outputvars_dict[op_name].extend(variable_list)
                  # fill var 'from_node'
                  for variable_name in variable_list:
                      all_vars[variable_name]["from_node"] = op_name
  
              attr_dict = {}
              attr_type_dict = {}
              for attr_name in op_desc.attr_names():
                  try:
                      if attr_name == "sub_block":
                          continue
                      attr_dict[attr_name] = op_desc.attr(attr_name)
                      attr_type = op_desc.attr_type(attr_name)
                      attr_type_dict[attr_name] = (
                          attr_type_name[attr_type]
                          if attr_type in attr_type_name
                          else str(attr_type).split(".")[1]
                      )
                  except Exception:
                      continue
              all_ops[op_name]["attrs"] = attr_dict
              all_ops[op_name]["attr_types"] = attr_type_dict
              all_ops[op_name]["children_node"] = []
              all_ops[op_name]["input_nodes"] = []
              all_ops[op_name]["output_nodes"] = []
              all_ops[op_name]["edge_input_nodes"] = []
              all_ops[op_name]["edge_output_nodes"] = []
  
      # second pass, create non-leaf nodes, fill 'parent_node', 'children_nodes' of nodes.
      for variable_name in all_vars:
          if all_vars[variable_name]["from_node"] == "":
              continue
          # some variable's input and output node are the same, we should prevent to show this situation as a cycle
          from_node_name = all_vars[variable_name]["from_node"]
          for to_node_name in all_vars[variable_name]["to_nodes"]:
              if to_node_name != from_node_name:
                  all_ops[from_node_name]["output_nodes"].append(
                      to_node_name
                  )
                  all_ops[to_node_name]["input_nodes"].append(
                      from_node_name
                  )
  
      general_children_dict = collections.defaultdict(set)
  
      all_op_names = list(all_ops.keys())
      for op_name in all_op_names:
          create_non_leaf_nodes(
              os.path.dirname(op_name),
              op_name,
              all_ops,
              general_children_dict,
          )
  
      # fill all non-leaf node's  'output_nodes' 'input_nodes' 'output_vars' 'input_vars'
      # post-order traverse tree
      post_order_results = []
  
      post_order_traverse("/", all_ops, post_order_results)
  
      for op_name in post_order_results:
          op = all_ops[op_name]
          op["children_node"] = list(op["children_node"])
  
          if op["children_node"]:
              for child_op in op["children_node"]:
                  for input_node in all_ops[child_op]["input_nodes"]:
                      if input_node in general_children_dict[op_name]:
                          continue
                      else:
                          op["input_nodes"].add(input_node)
                  for output_node in all_ops[child_op]["output_nodes"]:
                      if output_node in general_children_dict[op_name]:
                          continue
                      else:
                          op["output_nodes"].add(output_node)
                  for input_var in op_inputvars_dict[child_op]:
                      if (
                          all_vars[input_var]["from_node"]
                          not in general_children_dict[op_name]
                      ):
                          op["input_vars"].add(input_var)
                  for output_var in op_outputvars_dict[child_op]:
                      for to_node_name in all_vars[output_var][
                          "to_nodes"
                      ]:
                          if (
                              to_node_name
                              not in general_children_dict[op_name]
                          ):
                              op["output_vars"].add(output_var)
              op["input_nodes"] = list(op["input_nodes"])
              op["output_nodes"] = list(op["output_nodes"])
              op_inputvars_dict[op_name] = list(op["input_vars"])
              op_outputvars_dict[op_name] = list(op["output_vars"])
              op["input_vars"] = {"X": list(op["input_vars"])}
              op["output_vars"] = {"Y": list(op["output_vars"])}
  
      # Supplement edges and 'edge_input_nodes', 'edge_output_nodes' in op to help draw in frontend
      for var_name in all_vars.keys():
          construct_edges(var_name, all_ops, all_vars, all_edges)
  
      for src_node, to_node in all_edges.keys():
          all_ops[src_node]["edge_output_nodes"].append(to_node)
          all_ops[to_node]["edge_input_nodes"].append(src_node)
          all_edges[(src_node, to_node)]["vars"] = list(
              all_edges[(src_node, to_node)]["vars"]
          )
          if len(all_edges[(src_node, to_node)]["vars"]) > 1:
              all_edges[(src_node, to_node)]["label"] = (
                  str(len(all_edges[(src_node, to_node)]["vars"]))
                  + " tensors"
              )
          elif len(all_edges[(src_node, to_node)]["vars"]) == 1:
              all_edges[(src_node, to_node)]["label"] = str(
                  all_vars[all_edges[(src_node, to_node)]["vars"][0]][
                      "shape"
                  ]
              )
  
      final_data = {
          "version": _graph_version,
          "nodes": list(all_ops.values()),
          "vars": list(all_vars.values()),
          "edges": list(all_edges.values()),
      }
      return final_data
  
file_path: VisualDL/visualdl/component/graph/graph_component.py
imports: import collections
  import os.path
  import pathlib
  import re
  from .None import utils
label_desc: Use image node_id 4 for calling a global function with example usage: analyse_model(model_pb) and returns: final_data