docs: def _apply_xy_lims(ax: Axes, h: Union[Histogram1D, Histogram2D], data: np.ndarray, kwargs: dict):
      """Apply axis limits and scales from kwargs.
  
      Note: if exponential binning is used, the scale defaults to "log"
  
      Parameters
      ----------
      data : np.ndarray
          The frequencies or densities or otherwise manipulated data
      kwargs: dict
          xscale : Optional[str]
              If "log", the horizontal axis will use logarithmic scale
          yscale : Optional[str]
              If "log", the vertical axis will use logarithmic scale
          xlim : { "keep", "auto" } or tuple(float)
              "auto" (default) - the axis will fit first and last bin edges
              "keep" - let matlotlib figure this out
              tuple - standard parameter for set_xlim
          ylim : { "keep", "auto" } or tuple(float)
              "auto" (default)
                  - the axis will fit first and last bin edges (2D)
                  - the axis will exceed a bit the maximum value (1D)
              "keep" - let matlotlib figure this out
              tuple - standard parameter for set_ylim
          invert_y : Optional[bool]
              If True, higher values go down
  
      See Also
      --------
      plt.Axes.set_xlim, plt.Axes.set_ylim, plt.Axes.set_xscale, plt.Axes.set_yscale
      """
      ylim = kwargs.pop("ylim", "auto")
      xlim = kwargs.pop("xlim", "auto")
      invert_y = kwargs.pop("invert_y", False)
      xscale = yscale = None
  
      from ..binnings import ExponentialBinning
  
      if ylim is not "keep":
          if isinstance(ylim, tuple):
              pass
          elif ylim:
              ylim = ax.get_ylim()
              if h.ndim == 1:
                  xscale = kwargs.pop("xscale", "log" if isinstance(h.binning, ExponentialBinning) else None)
                  yscale = kwargs.pop("yscale", None)
                  if data.size > 0 and data.max() > 0:
                      ylim = (0, max(ylim[1], data.max() +
                                     (data.max() - ylim[0]) * 0.1))
                  if yscale == "log":
                      ylim = (abs(data[data > 0].min()) * 0.9, ylim[1] * 1.1)
              elif h.ndim == 2:
                  xscale = kwargs.pop("xscale", "log" if isinstance(h.binnings[0], ExponentialBinning) else None)
                  yscale = kwargs.pop("yscale", "log" if isinstance(h.binnings[1], ExponentialBinning) else None)
                  if h.shape[1] >= 2:
                      ylim = (h.get_bin_left_edges(1)[0],
                              h.get_bin_right_edges(1)[-1])
                      if yscale == "log":
                          if ylim[0] <= 0:
                              raise RuntimeError(
                                  "Cannot use logarithmic scale for non-positive bins.")
              else:
                  raise RuntimeError("Invalid dimension: {0}".format(h.ndim))
  
              if invert_y:
                  ylim = ylim[::-1]
                  # ax.xaxis.tick_top()
                  # ax.xaxis.set_label_position('top')
          ax.set_ylim(ylim)
  
      if xlim is not "keep":
          if isinstance(xlim, tuple):
              pass
          elif xlim:
              xlim = ax.get_xlim()
              if h.shape[0] >= 1:
                  if h.ndim == 1:
                      xlim = (h.bin_left_edges[0], h.bin_right_edges[-1])
                  elif h.ndim == 2:
                      xlim = (h.get_bin_left_edges(0)[
                              0], h.get_bin_right_edges(0)[-1])
                  else:
                      raise RuntimeError(
                          "Invalid dimension: {0}".format(h.ndim))
                  if xscale == "log":
                      if xlim[0] <= 0:
                          raise RuntimeError(
                              "Cannot use logarithmic scale for non-positive bins.")
          ax.set_xlim(*xlim)
  
      if xscale:
          ax.set_xscale(xscale)
      if yscale:
          ax.set_yscale(yscale)