code: def _layout_auto(graph, *args, **kwds):
      """Chooses and runs a suitable layout function based on simple
      topological properties of the graph.
  
      This function tries to choose an appropriate layout function for
      the graph using the following rules:
  
        1. If the graph has an attribute called C{layout}, it will be
           used. It may either be a L{Layout} instance, a list of
           coordinate pairs, the name of a layout function, or a
           callable function which generates the layout when called
           with the graph as a parameter.
  
        2. Otherwise, if the graph has vertex attributes called C{x}
           and C{y}, these will be used as coordinates in the layout.
           When a 3D layout is requested (by setting C{dim} to 3),
           a vertex attribute named C{z} will also be needed.
  
        3. Otherwise, if the graph is connected and has at most 100
           vertices, the Kamada-Kawai layout will be used (see
           L{GraphBase.layout_kamada_kawai()}).
  
        4. Otherwise, if the graph has at most 1000 vertices, the
           Fruchterman-Reingold layout will be used (see
           L{GraphBase.layout_fruchterman_reingold()}).
  
        5. If everything else above failed, the DrL layout algorithm
           will be used (see L{GraphBase.layout_drl()}).
  
      All the arguments of this function except C{dim} are passed on
      to the chosen layout function (in case we have to call some layout
      function).
  
      @keyword dim: specifies whether we would like to obtain a 2D or a
        3D layout.
      @return: a L{Layout} object.
      """
      if "layout" in graph.attributes():
          layout = graph["layout"]
          if isinstance(layout, Layout):
              # Layouts are used intact
              return layout
          if isinstance(layout, (list, tuple)):
              # Lists/tuples are converted to layouts
              return Layout(layout)
          if callable(layout):
              # Callables are called
              return Layout(layout(*args, **kwds))
          # Try Graph.layout()
          return graph.layout(layout, *args, **kwds)
  
      dim = kwds.get("dim", 2)
      vattrs = graph.vertex_attributes()
      if "x" in vattrs and "y" in vattrs:
          if dim == 3 and "z" in vattrs:
              return Layout(
                  list(zip(graph.vs["x"], graph.vs["y"], graph.vs["z"]))
              )
          else:
              return Layout(list(zip(graph.vs["x"], graph.vs["y"])))
  
      if graph.vcount() <= 100 and graph.is_connected():
          algo = "kk"
      elif graph.vcount() <= 1000:
          algo = "fr"
      else:
          algo = "drl"
      return graph.layout(algo, *args, **kwds)
  
imports: from math import sin, cos, pi
  from igraph._igraph import GraphBase
  from igraph.drawing.utils import BoundingBox
  from igraph.statistics import RunningMean
label_desc: Use image node_id 2 for calling a global function with example usage: _layout_auto(graph) and returns: graph, graph, layout, Layout, Layout, Layout, Layout