code: def adjust_text(
      texts,
      x=None,
      y=None,
      add_objects=None,
      ax=None,
      expand_text=(1.05, 1.2),
      expand_points=(1.05, 1.2),
      expand_objects=(1.05, 1.2),
      expand_align=(1.05, 1.2),
      autoalign="xy",
      va="center",
      ha="center",
      force_text=(0.1, 0.25),
      force_points=(0.2, 0.5),
      force_objects=(0.1, 0.25),
      lim=500,
      precision=0.01,
      only_move={"points": "xy", "text": "xy", "objects": "xy"},
      avoid_text=True,
      avoid_points=True,
      avoid_self=True,
      save_steps=False,
      save_prefix="",
      save_format="png",
      add_step_numbers=True,
      on_basemap=False,
      *args,
      **kwargs,
  ):
      """Iteratively adjusts the locations of texts.
  
      Call adjust_text the very last, after all plotting (especially
      anything that can change the axes limits) has been done. This is
      because to move texts the function needs to use the dimensions of
      the axes, and without knowing the final size of the plots the
      results will be completely nonsensical, or suboptimal.
  
      First moves all texts that are outside the axes limits
      inside. Then in each iteration moves all texts away from each
      other and from points. In the end hides texts and substitutes them
      with annotations to link them to the respective points.
  
      Parameters
      ----------
      texts : list
          A list of :obj:`matplotlib.text.Text` objects to adjust.
  
      Other Parameters
      ----------------
      x : array_like
          x-coordinates of points to repel from; if not provided only uses text
          coordinates.
      y : array_like
          y-coordinates of points to repel from; if not provided only uses text
          coordinates
      add_objects : list or PathCollection
          a list of additional matplotlib objects to avoid; they must have a
          `.get_window_extent()` method; alternatively, a PathCollection or a
          list of Bbox objects.
      ax : matplotlib axe, default is current axe (plt.gca())
          axe object with the plot
      expand_text : array_like, default (1.05, 1.2)
          a tuple/list/... with 2 multipliers (x, y) by which to expand the
          bounding box of texts when repelling them from each other.
      expand_points : array_like, default (1.05, 1.2)
          a tuple/list/... with 2 multipliers (x, y) by which to expand the
          bounding box of texts when repelling them from points.
      expand_objects : array_like, default (1.05, 1.2)
          a tuple/list/... with 2 multipliers (x, y) by which to expand the
          bounding box of texts when repelling them from other objects.
      expand_align : array_like, default (1.05, 1.2)
          a tuple/list/... with 2 multipliers (x, y) by which to expand the
          bounding box of texts when autoaligning texts.
      autoalign: str or boolean {'xy', 'x', 'y', True, False}, default 'xy'
          Direction in wich the best alignement will be determined
  
          - 'xy' or True, best alignment of all texts determined in all
            directions automatically before running the iterative adjustment
            (overriding va and ha),
          - 'x', will only align horizontally,
          - 'y', will only align vertically,
          - False, do nothing (i.e. preserve va and ha)
  
      va : str, default 'center'
          vertical alignment of texts
      ha : str, default 'center'
          horizontal alignment of texts,
      force_text : tuple, default (0.1, 0.25)
          the repel force from texts is multiplied by this value
      force_points : tuple, default (0.2, 0.5)
          the repel force from points is multiplied by this value
      force_objects : float, default (0.1, 0.25)
          same as other forces, but for repelling additional objects
      lim : int, default 500
          limit of number of iterations
      precision : float, default 0.01
          iterate until the sum of all overlaps along both x and y are less than
          this amount, as a fraction of the total widths and heights,
          respectively. May need to increase for complicated situations.
      only_move : dict, default {'points':'xy', 'text':'xy', 'objects':'xy'}
          a dict to restrict movement of texts to only certain axes for certain
          types of overlaps.
          Valid keys are 'points', 'text', and 'objects'.
          Valid values are '', 'x', 'y', and 'xy'.
          For example, only_move={'points':'y', 'text':'xy', 'objects':'xy'}
          forbids moving texts along the x axis due to overlaps with points.
      avoid_text : bool, default True
          whether to repel texts from each other.
      avoid_points : bool, default True
          whether to repel texts from points. Can be helpful to switch off in
          extremely crowded plots.
      avoid_self : bool, default True
          whether to repel texts from its original positions.
      save_steps : bool, default False
          whether to save intermediate steps as images.
      save_prefix : str, default ''
          if `save_steps` is True, a path and/or prefix to the saved steps.
      save_format : str, default 'png'
          if `save_steps` is True, a format to save the steps into.
      add_step_numbers : bool, default True
          if `save_steps` is True, whether to add step numbers as titles to the
          images of saving steps.
      on_basemap : bool, default False
          whether your plot uses the basemap library, stops labels going over the
          edge of the map.
      args and kwargs :
          any arguments will be fed into obj:`ax.annotate` after all the
          optimization is done just for plotting the connecting arrows if
          required.
  
      Return
      ------
      int
          Number of iteration
      """
      plt.draw()
      if ax is None:
          ax = plt.gca()
      r = get_renderer(ax.get_figure())
      orig_xy = [get_text_position(text, ax=ax) for text in texts]
      orig_x = [xy[0] for xy in orig_xy]
      orig_y = [xy[1] for xy in orig_xy]
      force_objects = float_to_tuple(force_objects)
      force_text = float_to_tuple(force_text)
      force_points = float_to_tuple(force_points)
  
      #    xdiff = np.diff(ax.get_xlim())[0]
      #    ydiff = np.diff(ax.get_ylim())[0]
  
      bboxes = get_bboxes(texts, r, (1.0, 1.0), ax)
      sum_width = np.sum(list(map(lambda bbox: bbox.width, bboxes)))
      sum_height = np.sum(list(map(lambda bbox: bbox.height, bboxes)))
      if not any(list(map(lambda val: "x" in val, only_move.values()))):
          precision_x = np.inf
      else:
          precision_x = precision * sum_width
      #
      if not any(list(map(lambda val: "y" in val, only_move.values()))):
          precision_y = np.inf
      else:
          precision_y = precision * sum_height
  
      if x is None:
          if y is None:
              if avoid_self:
                  x, y = orig_x, orig_y
              else:
                  x, y = [], []
          else:
              raise ValueError(
                  "Please specify both x and y, or neither"
              )
      if y is None:
          raise ValueError("Please specify both x and y, or neither")
      if add_objects is None:
          text_from_objects = False
          add_bboxes = []
      else:
          try:
              add_bboxes = get_bboxes(add_objects, r, (1, 1), ax)
          except ValueError:
              raise ValueError(
                  "Can't get bounding boxes from add_objects - is'\
                               it a flat list of matplotlib objects?"
              )
              return
          text_from_objects = True
      for text in texts:
          text.set_va(va)
          text.set_ha(ha)
      if save_steps:
          if add_step_numbers:
              plt.title("Before")
          plt.savefig(
              "%s%s.%s" % (save_prefix, "000a", save_format),
              format=save_format,
              dpi=150,
          )
      elif on_basemap:
          ax.draw(r)
  
      if autoalign:
          if autoalign is True:
              autoalign = "xy"
          for i in range(2):
              texts = optimally_align_text(
                  x,
                  y,
                  texts,
                  expand=expand_align,
                  add_bboxes=add_bboxes,
                  direction=autoalign,
                  renderer=r,
                  ax=ax,
              )
  
      if save_steps:
          if add_step_numbers:
              plt.title("Autoaligned")
          plt.savefig(
              "%s%s.%s" % (save_prefix, "000b", save_format),
              format=save_format,
              dpi=150,
          )
      elif on_basemap:
          ax.draw(r)
  
      texts = repel_text_from_axes(
          texts, ax, renderer=r, expand=expand_points
      )
      history = [(np.inf, np.inf)] * 10
      for i in xrange(lim):
          #        q1, q2 = [np.inf, np.inf], [np.inf, np.inf]
  
          if avoid_text:
              d_x_text, d_y_text, q1 = repel_text(
                  texts, renderer=r, ax=ax, expand=expand_text
              )
          else:
              d_x_text, d_y_text, q1 = (
                  [0] * len(texts),
                  [0] * len(texts),
                  (0, 0),
              )
  
          if avoid_points:
              d_x_points, d_y_points, q2 = repel_text_from_points(
                  x, y, texts, ax=ax, renderer=r, expand=expand_points
              )
          else:
              d_x_points, d_y_points, q2 = (
                  [0] * len(texts),
                  [0] * len(texts),
                  (0, 0),
              )
  
          if text_from_objects:
              d_x_objects, d_y_objects, q3 = repel_text_from_bboxes(
                  add_bboxes,
                  texts,
                  ax=ax,
                  renderer=r,
                  expand=expand_objects,
              )
          else:
              d_x_objects, d_y_objects, q3 = (
                  [0] * len(texts),
                  [0] * len(texts),
                  (0, 0),
              )
  
          if only_move:
              if "text" in only_move:
                  if "x" not in only_move["text"]:
                      d_x_text = np.zeros_like(d_x_text)
                  if "y" not in only_move["text"]:
                      d_y_text = np.zeros_like(d_y_text)
              if "points" in only_move:
                  if "x" not in only_move["points"]:
                      d_x_points = np.zeros_like(d_x_points)
                  if "y" not in only_move["points"]:
                      d_y_points = np.zeros_like(d_y_points)
              if "objects" in only_move:
                  if "x" not in only_move["objects"]:
                      d_x_objects = np.zeros_like(d_x_objects)
                  if "y" not in only_move["objects"]:
                      d_y_objects = np.zeros_like(d_y_objects)
  
          dx = (
              np.array(d_x_text) * force_text[0]
              + np.array(d_x_points) * force_points[0]
              + np.array(d_x_objects) * force_objects[0]
          )
          dy = (
              np.array(d_y_text) * force_text[1]
              + np.array(d_y_points) * force_points[1]
              + np.array(d_y_objects) * force_objects[1]
          )
          qx = np.sum([q[0] for q in [q1, q2, q3]])
          qy = np.sum([q[1] for q in [q1, q2, q3]])
          histm = np.max(np.array(history), axis=0)
          history.pop(0)
          history.append((qx, qy))
          move_texts(
              texts,
              dx,
              dy,
              bboxes=get_bboxes(texts, r, (1, 1), ax),
              ax=ax,
          )
          if save_steps:
              if add_step_numbers:
                  plt.title(i + 1)
              plt.savefig(
                  "%s%s.%s"
                  % (save_prefix, "{0:03}".format(i + 1), save_format),
                  format=save_format,
                  dpi=150,
              )
          elif on_basemap:
              ax.draw(r)
          # Stop if we've reached the precision threshold,
          # or if the x and y displacement
          # are both greater than the max over the last
          # 10 iterations (suggesting a
          # failure to converge)
          if (qx < precision_x and qy < precision_y) or np.all(
              [qx, qy] >= histm
          ):
              break
          # Now adding arrows from texts to their original locations if required
      if "arrowprops" in kwargs:
          bboxes = get_bboxes(texts, r, (1, 1), ax)
          kwap = kwargs.pop("arrowprops")
          for j, (bbox, text) in enumerate(zip(bboxes, texts)):
              ap = {
                  "patchA": text
              }  # Ensure arrow is clipped by the text
              ap.update(kwap)  # Add arrowprops from kwargs
              ax.annotate(
                  "",  # Add an arrow from the text to the point
                  xy=(orig_xy[j]),
                  xytext=get_midpoint(bbox),
                  arrowprops=ap,
                  *args,
                  **kwargs,
              )
  
      if save_steps:
          if add_step_numbers:
              plt.title(i + 1)
              plt.savefig(
                  "%s%s.%s"
                  % (save_prefix, "{0:03}".format(i + 1), save_format),
                  format=save_format,
                  dpi=150,
              )
      elif on_basemap:
          ax.draw(r)
  
      return i + 1
  
imports: from __future__ import division
  import sys
  from itertools import product
  from operator import itemgetter
  import matplotlib
  import numpy
  from matplotlib import pyplot
  from matplotlib.path import get_path_collection_extents
label_desc: Use image node_id 15 for calling a global function with example usage: adjust_text(texts, x, y, add_objects, ax, expand_text, expand_points, expand_objects, expand_align, autoalign, va, ha, force_text, force_points, force_objects, lim, precision, only_move, avoid_text, avoid_points, avoid_save_steps, save_prefix, save_format, add_step_numbers, on_basemap) and returns: unknown