code: def format_plot(
      ax,
      save_path: Optional[str],
      show_sample_info: str,
      to_log: bool,
      circ_patches: List[patches.Patch],
      y_lim: float,
      y_lim_min: float,
      convert_to_percent: bool,
      x_label: str,
      y_label: str,
      font_size_1: int,
      font_size_2: int,
      bin_label_locs: List[float],
      x_axis_labels: List[str],
      num_bins: int,
      uncertainty_types_list: List[List[str]],
      all_sample_percs: List[List[float]],
      all_sample_label_x_locs: List[List[Any]],
      max_bin_height: float,
      comparing_q: bool = False,
  ) -> None:
      """
      This function takes a matplotlib Axes object and formats the plot according to the provided parameters.
  
      Args:
          ax: A matplotlib axes object to be formatted.
          save_path: The path where the plot should be saved. If None, the plot will be shown using plt.show().
          show_sample_info: Determines how sample information is displayed. Can be "None", "Average", or "All".
          to_log: If True, sets the y-axis to log scale.
          circ_patches: List of matplotlib patches to be added to the legend.
          y_lim: The upper limit for the y-axis.
          y_lim_min: The lower limit for the y-axis.
          convert_to_percent: If True, converts y-axis values to percentages.
          x_label: The label for the x-axis.
          y_label: The label for the y-axis.
          font_size_1: The font size for the axis labels.
          font_size_2: The font size for the tick labels.
          bin_label_locs: The x-axis locations of the bin labels.
          x_axis_labels: The labels for the x-axis.
          num_bins: The number of bins.
          uncertainty_types_list: The list of uncertainty types.
          all_sample_percs: The percentage of samples for each bin.
          all_sample_label_x_locs: The x-axis locations of the sample percentage labels.
          max_bin_height: The maximum height of a bin in the plot.
          comparing_q: If True, it uses a ticker.FixedFormatter for the x-axis.
  
      Returns:
          None
      """
  
      # Show the average samples on top of boxplots, aligned. if lots of bins we can lower the height.
      if show_sample_info != "None":
          for idx_text, perc_info in enumerate(all_sample_percs):
              if show_sample_info == "Average":
                  ax.text(
                      all_sample_label_x_locs[idx_text],
                      max_bin_height * 0.8,  # Position
                      r"$\bf{PSB}$"
                      + ": \n"
                      + r"${} \pm$".format(perc_info[0])
                      + "\n"
                      + r"${}$".format(perc_info[1]),
                      verticalalignment="bottom",  # Centered bottom with line
                      horizontalalignment="center",  # Centered with horizontal line
                      fontsize=25,
                  )
              elif show_sample_info == "All":
                  if idx_text % 2 == 0:
                      label_height = max_bin_height + 3
                  else:
                      label_height = max_bin_height + 1
                  ax.text(
                      all_sample_label_x_locs[idx_text][0],
                      label_height,  # Position
                      r"$\bf{PSB}$" + ": \n" + str(perc_info) + "%",
                      verticalalignment="bottom",  # Centered bottom with line
                      horizontalalignment="center",  # Centered with horizontal line
                      fontsize=25,
                  )
  
      ax.set_xlabel(x_label, fontsize=font_size_1)
      ax.set_ylabel(y_label, fontsize=font_size_1)
      ax.set_xticks(bin_label_locs)
  
      plt.subplots_adjust(bottom=0.15)
      plt.subplots_adjust(left=0.15)
  
      plt.xticks(fontsize=font_size_2)
      plt.yticks(fontsize=font_size_2)
  
      if comparing_q:
          ax.xaxis.set_major_formatter(
              ticker.FixedFormatter(x_axis_labels)
          )
  
      else:
          if num_bins <= 5:
              ax.xaxis.set_major_formatter(
                  ticker.FixedFormatter(
                      x_axis_labels[:-1]
                      * (len(uncertainty_types_list) * 2)
                  )
              )
          # If too many bins, only show the first and last or it will appear too squished, indicate direction with arrow.
          elif num_bins < 15:
              number_blanks_0 = [
                  "" for x in range(math.floor((num_bins - 3) / 2))
              ]
              number_blanks_1 = [
                  "" for x in range(num_bins - 3 - len(number_blanks_0))
              ]
              new_labels = (
                  [x_axis_labels[0]]
                  + number_blanks_0
                  + [r"$\rightarrow$"]
                  + number_blanks_1
                  + [x_axis_labels[-1]]
              )
              ax.xaxis.set_major_formatter(
                  ticker.FixedFormatter(
                      new_labels * (len(uncertainty_types_list) * 2)
                  )
              )
          # if more than 15 bins, we must move the first and last labels inwards to prevent overlap.
          else:
              number_blanks_0 = [
                  "" for x in range(math.floor((num_bins - 5) / 2))
              ]
              number_blanks_1 = [
                  "" for x in range(num_bins - 5 - len(number_blanks_0))
              ]
              new_labels = (
                  [""]
                  + [x_axis_labels[0]]
                  + number_blanks_0
                  + [r"$\rightarrow$"]
                  + number_blanks_1
                  + [x_axis_labels[-1]]
                  + [""]
              )
              ax.xaxis.set_major_formatter(
                  ticker.FixedFormatter(
                      new_labels * (len(uncertainty_types_list) * 2)
                  )
              )
  
      if to_log:
          ax.set_yscale("symlog", base=2)
          ax.yaxis.set_major_formatter(ScalarFormatter())
          ax.set_ylim(y_lim_min, y_lim)
  
      else:
          ax.set_ylim((y_lim_min, y_lim))
  
      # If using percent, doesnt make sense to show any y tick above 100
      if convert_to_percent and y_lim > 100:
          plt.yticks(np.arange(0, y_lim, 20))
  
      # Add more to legend, add the mean symbol and median symbol.
      red_triangle_mean = mlines.Line2D(
          [],
          [],
          color="crimson",
          marker="^",
          markeredgecolor="black",
          linestyle="None",
          markersize=10,
          label="Mean",
      )
      circ_patches.append(red_triangle_mean)
  
      red_line_median = mlines.Line2D(
          [],
          [],
          color="crimson",
          marker="",
          markeredgecolor="black",
          markersize=10,
          label="Median",
      )
      circ_patches.append(red_line_median)
  
      if show_sample_info == "Average":
          circ_patches.append(
              patches.Patch(
                  color="none",
                  label=r"$\bf{PSB}$" + r": % Samples per Bin",
              )
          )
  
      num_cols_legend = math.ceil(len(circ_patches) / 2)
      ax.legend(
          handles=circ_patches,
          fontsize=20,
          ncol=num_cols_legend,
          columnspacing=2,
          loc="upper center",
          bbox_to_anchor=(0.5, 1.18),
          fancybox=True,
          shadow=False,
      )
  
      if save_path is not None:
          plt.gcf().set_size_inches(16.0, 10.0)
          plt.tight_layout()
          plt.savefig(
              save_path, dpi=600, bbox_inches="tight", pad_inches=0.1
          )
          plt.close()
      else:
          plt.gcf().set_size_inches(16.0, 10.0)
          plt.show()
          plt.close()
  
imports: import logging
  import math
  import os
  from typing import Any, Dict, List, Optional, Tuple, Union
  import matplotlib.lines
  import matplotlib.patches
  import matplotlib.pyplot
  import matplotlib.ticker
  import numpy
  import pandas
  import pwlf
  from matplotlib.ticker import ScalarFormatter
  from scipy import stats
  from sklearn.isotonic import IsotonicRegression
  from kale.evaluate.similarity_metrics import evaluate_correlations
  from kale.evaluate.uncertainty_metrics import evaluate_bounds, evaluate_jaccard, get_mean_errors
  from kale.prepdata.tabular_transform import generate_struct_for_qbin
  from kale.utils.save_xlsx import generate_summary_df
label_desc: Use image node_id 4 for calling a global function with example usage: format_plot(ax, save_path, show_sample_info, to_log, circ_patches, y_lim, y_lim_min, convert_to_percent, x_label, y_label, font_size_1, font_size_2, bin_label_locs, x_axis_labels, num_bins, uncertainty_types_list, all_sample_percs, all_sample_label_x_locs, max_bin_height, comparing_q) without return types