class_docstr: Models a perception module inference graph.
          Conditions on using the InferenceGraph object:
              1. All keys of the perception_blocks dictionary have to be unique
              2. All out_keys used when creating the blocks have to be unique
              3. All out_keys of a given block have to be sub-strings of the blocks key in the perception_blocks dict
  
  :param inference_block: An inference perception block to build the graph for.
class_docstr_tok: ["Models","a","perception","module","inference","graph",".","Conditions","on","using","the","InferenceGraph","object",":","1",".","All","keys","of","the","perception_blocks","dictionary","have","to","be","unique","2",".","All","out_keys","used","when","creating","the","blocks","have","to","be","unique","3",".","All","out_keys","of","a","given","block","have","to","be","sub-strings","of","the","blocks","key","in","the","perception_blocks","dict",":","param","inference_block",":","An","inference","perception","block","to","build","the","graph","for","."]
docstr: Draws the inference graph using matplotlib.
  
  :param name: The name of the network to be drawn (used in the tile only)
  :param figure_size: The figure size to be drawn. If None, the size is inferred (does not work well for saving
      though.
docstr_tok: ["Draws","the","inference","graph","using","matplotlib",".",":","param","name",":","The","name","of","the","network","to","be","drawn","(","used","in","the","tile","only",")",":","param","figure_size",":","The","figure","size","to","be","drawn",".","If","None",",","the","size","is","inferred","(","does","not","work","well","for","saving","though","."]
code: def _draw(
      self, name: str, figure_size: Optional[Tuple[int, int]]
  ) -> None:
      """Draws the inference graph using matplotlib.
  
      :param name: The name of the network to be drawn (used in the tile only)
      :param figure_size: The figure size to be drawn. If None, the size is inferred (does not work well for saving
          though.
      """
  
      fig = plt.figure(figsize=figure_size)
      plt.clf()
      renderer = fig.canvas.get_renderer()
  
      # get relevant node labels
      labels = nx.get_node_attributes(self.node_graph, "label")
      is_block = nx.get_node_attributes(self.node_graph, "is_block")
      num_params = nx.get_node_attributes(self.node_graph, "num_params")
      pos = nx.nx_agraph.graphviz_layout(self.node_graph, prog="dot")
  
      max_params_per_node = max(num_params.values())
  
      # draw nodes
      bbox_heights = dict()
      for node in self.node_graph.nodes():
          x, y = pos[node]
          if not is_block[node]:
              color = "indianred"
              alpha = 0.15
          elif num_params[node] == 0:
              color = "powderblue"
              alpha = 0.1
          else:
              color = "lightskyblue"
              alpha = (
                  float(num_params[node]) / max_params_per_node * 0.3
                  + 0.1
              )
          obj = plt.text(
              x,
              y,
              labels[node],
              picker=True,
              ha="center",
              va="center",
              bbox=dict(boxstyle="round", facecolor=color, alpha=alpha),
          )
          plt.plot(x, y, "bo", markersize=0)
  
          # get bbox height
          bbox_height = obj.get_window_extent(renderer).height
          bbox_heights[node] = bbox_height
  
      # draw edges
      for src_node, dst_node, attrs in self.node_graph.edges(data=True):
          src_x, src_y = pos[src_node]
          dst_x, dst_y = pos[dst_node]
          src_y -= (bbox_heights[src_node] // 4 * 3) + 2
          dst_y += (bbox_heights[dst_node] // 4 * 3) + 2
          plt.annotate(
              "",
              xy=(dst_x, dst_y),
              xytext=(src_x, src_y),
              arrowprops=dict(arrowstyle="->"),
          )
  
      plt.axis("off")
      title = f"Graphical depiction of '{name}'"
      title += f" with {self._total_num_of_params:,} parameters"
      plt.title(title)
      plt.tight_layout()
  
imports: import os
  import pickle
  from typing import Union, List, Dict, Optional, Sequence, Tuple
  import networkx
  import torch
  from matplotlib import pyplot
  from torch import nn
  from maze.core.annotations import override
  from maze.perception.blocks.base import PerceptionBlock
label_desc: Use image node_id 4 for calling the InferenceGraph obj's underlying member method code with example usage: obj._draw(name, figure_size) without return types