code: def streamplot(
      axes,
      x,
      y,
      u,
      v,
      density=1,
      linewidth=None,
      color=None,
      cmap=None,
      norm=None,
      arrowsize=1,
      arrowstyle="-|>",
      minlength=0.1,
      transform=None,
      zorder=None,
      start_points=None,
      maxlength=4.0,
      integration_direction="both",
      broken_streamlines=True,
  ):
      """
      Draw streamlines of a vector flow.
  
      Parameters
      ----------
      x, y : 1D/2D arrays
          Evenly spaced strictly increasing arrays to make a grid.  If 2D, all
          rows of *x* must be equal and all columns of *y* must be equal; i.e.,
          they must be as if generated by ``np.meshgrid(x_1d, y_1d)``.
      u, v : 2D arrays
          *x* and *y*-velocities. The number of rows and columns must match
          the length of *y* and *x*, respectively.
      density : float or (float, float)
          Controls the closeness of streamlines. When ``density = 1``, the domain
          is divided into a 30x30 grid. *density* linearly scales this grid.
          Each cell in the grid can have, at most, one traversing streamline.
          For different densities in each direction, use a tuple
          (density_x, density_y).
      linewidth : float or 2D array
          The width of the streamlines. With a 2D array the line width can be
          varied across the grid. The array must have the same shape as *u*
          and *v*.
      color : color or 2D array
          The streamline color. If given an array, its values are converted to
          colors using *cmap* and *norm*.  The array must have the same shape
          as *u* and *v*.
      cmap, norm
          Data normalization and colormapping parameters for *color*; only used
          if *color* is an array of floats. See `~.Axes.imshow` for a detailed
          description.
      arrowsize : float
          Scaling factor for the arrow size.
      arrowstyle : str
          Arrow style specification.
          See `~matplotlib.patches.FancyArrowPatch`.
      minlength : float
          Minimum length of streamline in axes coordinates.
      start_points : (N, 2) array
          Coordinates of starting points for the streamlines in data coordinates
          (the same coordinates as the *x* and *y* arrays).
      zorder : float
          The zorder of the streamlines and arrows.
          Artists with lower zorder values are drawn first.
      maxlength : float
          Maximum length of streamline in axes coordinates.
      integration_direction : {'forward', 'backward', 'both'}, default: 'both'
          Integrate the streamline in forward, backward or both directions.
      data : indexable object, optional
          DATA_PARAMETER_PLACEHOLDER
      broken_streamlines : boolean, default: True
          If False, forces streamlines to continue until they
          leave the plot domain.  If True, they may be terminated if they
          come too close to another streamline.
  
      Returns
      -------
      StreamplotSet
          Container object with attributes
  
          - ``lines``: `.LineCollection` of streamlines
  
          - ``arrows``: `.PatchCollection` containing `.FancyArrowPatch`
            objects representing the arrows half-way along streamlines.
  
          This container will probably change in the future to allow changes
          to the colormap, alpha, etc. for both lines and arrows, but these
          changes should be backward compatible.
      """
      grid = Grid(x, y)
      mask = StreamMask(density)
      dmap = DomainMap(grid, mask)
  
      if zorder is None:
          zorder = mlines.Line2D.zorder
  
      # default to data coordinates
      if transform is None:
          transform = axes.transData
  
      if color is None:
          color = axes._get_lines.get_next_color()
  
      if linewidth is None:
          linewidth = mpl.rcParams["lines.linewidth"]
  
      line_kw = {}
      arrow_kw = dict(
          arrowstyle=arrowstyle, mutation_scale=10 * arrowsize
      )
  
      _api.check_in_list(
          ["both", "forward", "backward"],
          integration_direction=integration_direction,
      )
  
      if integration_direction == "both":
          maxlength /= 2.0
  
      use_multicolor_lines = isinstance(color, np.ndarray)
      if use_multicolor_lines:
          if color.shape != grid.shape:
              raise ValueError(
                  "If 'color' is given, it must match the shape of "
                  "the (x, y) grid"
              )
          line_colors = [
              []
          ]  # Empty entry allows concatenation of zero arrays.
          color = np.ma.masked_invalid(color)
      else:
          line_kw["color"] = color
          arrow_kw["color"] = color
  
      if isinstance(linewidth, np.ndarray):
          if linewidth.shape != grid.shape:
              raise ValueError(
                  "If 'linewidth' is given, it must match the "
                  "shape of the (x, y) grid"
              )
          line_kw["linewidth"] = []
      else:
          line_kw["linewidth"] = linewidth
          arrow_kw["linewidth"] = linewidth
  
      line_kw["zorder"] = zorder
      arrow_kw["zorder"] = zorder
  
      # Sanity checks.
      if u.shape != grid.shape or v.shape != grid.shape:
          raise ValueError(
              "'u' and 'v' must match the shape of the (x, y) grid"
          )
  
      u = np.ma.masked_invalid(u)
      v = np.ma.masked_invalid(v)
  
      integrate = _get_integrator(
          u, v, dmap, minlength, maxlength, integration_direction
      )
  
      trajectories = []
      if start_points is None:
          for xm, ym in _gen_starting_points(mask.shape):
              if mask[ym, xm] == 0:
                  xg, yg = dmap.mask2grid(xm, ym)
                  t = integrate(xg, yg, broken_streamlines)
                  if t is not None:
                      trajectories.append(t)
      else:
          sp2 = np.asanyarray(start_points, dtype=float).copy()
  
          # Check if start_points are outside the data boundaries
          for xs, ys in sp2:
              if not (
                  grid.x_origin <= xs <= grid.x_origin + grid.width
                  and grid.y_origin <= ys <= grid.y_origin + grid.height
              ):
                  raise ValueError(
                      f"Starting point ({xs}, {ys}) outside of "
                      "data boundaries"
                  )
  
          # Convert start_points from data to array coords
          # Shift the seed points from the bottom left of the data so that
          # data2grid works properly.
          sp2[:, 0] -= grid.x_origin
          sp2[:, 1] -= grid.y_origin
  
          for xs, ys in sp2:
              xg, yg = dmap.data2grid(xs, ys)
              # Floating point issues can cause xg, yg to be slightly out of
              # bounds for xs, ys on the upper boundaries. Because we have
              # already checked that the starting points are within the original
              # grid, clip the xg, yg to the grid to work around this issue
              xg = np.clip(xg, 0, grid.nx - 1)
              yg = np.clip(yg, 0, grid.ny - 1)
  
              t = integrate(xg, yg, broken_streamlines)
              if t is not None:
                  trajectories.append(t)
  
      if use_multicolor_lines:
          if norm is None:
              norm = mcolors.Normalize(color.min(), color.max())
          cmap = cm._ensure_cmap(cmap)
  
      streamlines = []
      arrows = []
      for t in trajectories:
          tgx, tgy = t.T
          # Rescale from grid-coordinates to data-coordinates.
          tx, ty = dmap.grid2data(tgx, tgy)
          tx += grid.x_origin
          ty += grid.y_origin
  
          # Create multiple tiny segments if varying width or color is given
          if isinstance(linewidth, np.ndarray) or use_multicolor_lines:
              points = np.transpose([tx, ty]).reshape(-1, 1, 2)
              streamlines.extend(np.hstack([points[:-1], points[1:]]))
          else:
              points = np.transpose([tx, ty])
              streamlines.append(points)
  
          # Add arrows halfway along each trajectory.
          s = np.cumsum(np.hypot(np.diff(tx), np.diff(ty)))
          n = np.searchsorted(s, s[-1] / 2.0)
          arrow_tail = (tx[n], ty[n])
          arrow_head = (np.mean(tx[n : n + 2]), np.mean(ty[n : n + 2]))
  
          if isinstance(linewidth, np.ndarray):
              line_widths = interpgrid(linewidth, tgx, tgy)[:-1]
              line_kw["linewidth"].extend(line_widths)
              arrow_kw["linewidth"] = line_widths[n]
  
          if use_multicolor_lines:
              color_values = interpgrid(color, tgx, tgy)[:-1]
              line_colors.append(color_values)
              arrow_kw["color"] = cmap(norm(color_values[n]))
  
          p = patches.FancyArrowPatch(
              arrow_tail, arrow_head, transform=transform, **arrow_kw
          )
          arrows.append(p)
  
      lc = mcollections.LineCollection(
          streamlines, transform=transform, **line_kw
      )
      lc.sticky_edges.x[:] = [grid.x_origin, grid.x_origin + grid.width]
      lc.sticky_edges.y[:] = [
          grid.y_origin,
          grid.y_origin + grid.height,
      ]
      if use_multicolor_lines:
          lc.set_array(np.ma.hstack(line_colors))
          lc.set_cmap(cmap)
          lc.set_norm(norm)
      axes.add_collection(lc)
  
      ac = mcollections.PatchCollection(arrows)
      # Adding the collection itself is broken; see #2341.
      for p in arrows:
          axes.add_patch(p)
  
      axes.autoscale_view()
      stream_container = StreamplotSet(lc, ac)
      return stream_container
  
imports: import numpy
  import matplotlib
  from matplotlib import _api, cm, patches
  import matplotlib.colors
  import matplotlib.collections
  import matplotlib.lines
label_desc: Use image node_id 1 for calling a global function with example usage: streamplot(axes, x, y, u, v, density, linewidth, color, cmap, norm, arrowsize, arrowstyle, minlength, transform, zorder, start_points, maxlength, integration_direction, broken_streamlines) and returns: stream_container