code: def model_to_dot(
      model,
      show_shapes=False,
      show_dtype=False,
      show_layer_names=True,
      rankdir="TB",
      expand_nested=False,
      dpi=200,
      subgraph=False,
      show_layer_activations=False,
      show_trainable=False,
      **kwargs,
  ):
      """Convert a Keras model to dot format.
  
      Args:
          model: A Keras model instance.
          show_shapes: whether to display shape information.
          show_dtype: whether to display layer dtypes.
          show_layer_names: whether to display layer names.
          rankdir: `rankdir` argument passed to PyDot,
              a string specifying the format of the plot: `"TB"`
              creates a vertical plot; `"LR"` creates a horizontal plot.
          expand_nested: whether to expand nested Functional models
              into clusters.
          dpi: Image resolution in dots per inch.
          subgraph: whether to return a `pydot.Cluster` instance.
          show_layer_activations: Display layer activations (only for layers that
              have an `activation` property).
          show_trainable: whether to display if a layer is trainable.
  
      Returns:
          A `pydot.Dot` instance representing the Keras model or
          a `pydot.Cluster` instance representing nested model if
          `subgraph=True`.
      """
      from keras.ops.function import make_node_key
  
      if not model.built:
          raise ValueError(
              "This model has not yet been built. "
              "Build the model first by calling `build()` or by calling "
              "the model on a batch of data."
          )
  
      from keras.models import functional
      from keras.models import sequential
  
      # from keras.layers import Wrapper
  
      if not check_pydot():
          raise ImportError(
              "You must install pydot (`pip install pydot`) for "
              "model_to_dot to work."
          )
  
      if subgraph:
          dot = pydot.Cluster(style="dashed", graph_name=model.name)
          dot.set("label", model.name)
          dot.set("labeljust", "l")
      else:
          dot = pydot.Dot()
          dot.set("rankdir", rankdir)
          dot.set("concentrate", True)
          dot.set("dpi", dpi)
          dot.set("splines", "ortho")
          dot.set_node_defaults(shape="record")
  
      if kwargs.pop("layer_range", None) is not None:
          raise ValueError(
              "Argument `layer_range` is no longer supported."
          )
      if kwargs:
          raise ValueError(f"Unrecognized keyword arguments: {kwargs}")
  
      kwargs = {
          "show_layer_names": show_layer_names,
          "show_layer_activations": show_layer_activations,
          "show_dtype": show_dtype,
          "show_shapes": show_shapes,
          "show_trainable": show_trainable,
      }
  
      if isinstance(model, sequential.Sequential):
          # TODO
          layers = model.layers
      elif not isinstance(model, functional.Functional):
          # We treat subclassed models as a single node.
          node = make_node(model, **kwargs)
          dot.add_node(node)
          return dot
      else:
          layers = model._operations
  
      # Create graph nodes.
      sub_n_first_node = {}
      sub_n_last_node = {}
      for i, layer in enumerate(layers):
          # Process nested functional models.
          if expand_nested and isinstance(layer, functional.Functional):
              submodel = model_to_dot(
                  layer,
                  show_shapes,
                  show_dtype,
                  show_layer_names,
                  rankdir,
                  expand_nested,
                  subgraph=True,
                  show_layer_activations=show_layer_activations,
                  show_trainable=show_trainable,
              )
              # sub_n : submodel
              sub_n_nodes = submodel.get_nodes()
              sub_n_first_node[layer.name] = sub_n_nodes[0]
              sub_n_last_node[layer.name] = sub_n_nodes[-1]
              dot.add_subgraph(submodel)
  
          else:
              node = make_node(layer, **kwargs)
              dot.add_node(node)
  
      # Connect nodes with edges.
      # Sequential case.
      if isinstance(model, sequential.Sequential):
          for i in range(len(layers) - 1):
              inbound_layer_id = str(id(layers[i]))
              layer_id = str(id(layers[i + 1]))
              add_edge(dot, inbound_layer_id, layer_id)
          return dot
  
      # Functional case.
      for i, layer in enumerate(layers):
          layer_id = str(id(layer))
          for i, node in enumerate(layer._inbound_nodes):
              node_key = make_node_key(layer, i)
              if node_key in model._nodes:
                  for parent_node in node.parent_nodes:
                      inbound_layer = parent_node.operation
                      inbound_layer_id = str(id(inbound_layer))
                      if not expand_nested:
                          assert dot.get_node(inbound_layer_id)
                          assert dot.get_node(layer_id)
                          add_edge(dot, inbound_layer_id, layer_id)
                      else:
                          # if inbound_layer is not Functional
                          if not isinstance(
                              inbound_layer, functional.Functional
                          ):
                              # if current layer is not Functional
                              if not isinstance(
                                  layer, functional.Functional
                              ):
                                  assert dot.get_node(inbound_layer_id)
                                  assert dot.get_node(layer_id)
                                  add_edge(
                                      dot, inbound_layer_id, layer_id
                                  )
                              # if current layer is Functional
                              elif isinstance(
                                  layer, functional.Functional
                              ):
                                  add_edge(
                                      dot,
                                      inbound_layer_id,
                                      sub_n_first_node[
                                          layer.name
                                      ].get_name(),
                                  )
                          # if inbound_layer is Functional
                          elif isinstance(
                              inbound_layer, functional.Functional
                          ):
                              name = sub_n_last_node[
                                  inbound_layer.name
                              ].get_name()
                              if isinstance(
                                  layer, functional.Functional
                              ):
                                  output_name = sub_n_first_node[
                                      layer.name
                                  ].get_name()
                                  add_edge(dot, name, output_name)
                              else:
                                  add_edge(dot, name, layer_id)
      return dot
  
file_path: keras/keras/utils/model_visualization.py
imports: import os
  import sys
  from keras.api_export import keras_export
  from keras.utils import io_utils
label_desc: Use image node_id 7 for calling a global function with example usage: model_to_dot(model, show_shapes, show_dtype, show_layer_names, rankdir, expand_nested, dpi, subgraph, show_layer_activations, show_trainable) and returns: dot, dot, dot