code: def _create_ranges(exprs, ranges, npar, label="", params=None):
      """This function does two things:
  
      1. Check if the number of free symbols is in agreement with the type of
         plot chosen. For example, plot() requires 1 free symbol;
         plot3d() requires 2 free symbols.
      2. Sometime users create plots without providing ranges for the variables.
         Here we create the necessary ranges.
  
      Parameters
      ==========
  
      exprs : iterable
          The expressions from which to extract the free symbols
      ranges : iterable
          The limiting ranges provided by the user
      npar : int
          The number of free symbols required by the plot functions.
          For example,
          npar=1 for plot, npar=2 for plot3d, ...
      params : dict
          A dictionary mapping symbols to parameters for interactive plot.
      """
      get_default_range = lambda symbol: Tuple(symbol, -10, 10)
  
      free_symbols = _get_free_symbols(exprs)
      if params is not None:
          free_symbols = free_symbols.difference(params.keys())
  
      if len(free_symbols) > npar:
          raise ValueError(
              "Too many free symbols.\n"
              + "Expected {} free symbols.\n".format(npar)
              + "Received {}: {}".format(
                  len(free_symbols), free_symbols
              )
          )
  
      if len(ranges) > npar:
          raise ValueError(
              "Too many ranges. Received %s, expected %s"
              % (len(ranges), npar)
          )
  
      # free symbols in the ranges provided by the user
      rfs = set().union([r[0] for r in ranges])
      if len(rfs) != len(ranges):
          raise ValueError("Multiple ranges with the same symbol")
  
      if len(ranges) < npar:
          symbols = free_symbols.difference(rfs)
          if symbols != set():
              # add a range for each missing free symbols
              for s in symbols:
                  ranges.append(get_default_range(s))
          # if there is still room, fill them with dummys
          for i in range(npar - len(ranges)):
              ranges.append(get_default_range(Dummy()))
  
      if len(free_symbols) == npar:
          # there could be times when this condition is not met, for example
          # plotting the function f(x, y) = x (which is a plane); in this case,
          # free_symbols = {x} whereas rfs = {x, y} (or x and Dummy)
          rfs = set().union([r[0] for r in ranges])
          if len(free_symbols.difference(rfs)) > 0:
              raise ValueError(
                  "Incompatible free symbols of the expressions with "
                  "the ranges.\n"
                  + "Free symbols in the expressions: {}\n".format(
                      free_symbols
                  )
                  + "Free symbols in the ranges: {}".format(rfs)
              )
      return ranges
  
file_path: sympy/sympy/plotting/utils.py
imports: from sympy.core.containers import Tuple
  from sympy.core.basic import Basic
  from sympy.core.expr import Expr
  from sympy.core.function import AppliedUndef
  from sympy.core.relational import Relational
  from sympy.core.symbol import Dummy
  from sympy.core.sympify import sympify
  from sympy.logic.boolalg import BooleanFunction
  from sympy.sets.fancysets import ImageSet
  from sympy.sets.sets import FiniteSet
  from sympy.tensor.indexed import Indexed
label_desc: Use image node_id 4 for calling a global function with example usage: _create_ranges(exprs, ranges, npar, label, params) and returns: ranges