code: def quantile_binning_and_est_errors(
      errors: List[float],
      uncertainties: List[float],
      num_bins: int,
      type: str = "quantile",
      acceptable_thresh: float = 5,
      combine_middle_bins: bool = False,
  ) -> Tuple[List[List[float]], List[float]]:
      """
      Calculate quantile thresholds, and isotonically regress errors and uncertainties
      and get estimated error bounds.
  
      Args:
          errors (List[float]): List of errors.
          uncertainties (List[float]): List of uncertainties.
          num_bins (int): Number of quantile bins.
          type (str, optional): Type of thresholds to calculate, "quantile" recommended.
                                Defaults to "quantile".
          acceptable_thresh (float, optional): Acceptable error threshold. Only relevant
                                               if type="error-wise". Defaults to 5.
          combine_middle_bins (bool, optional): Whether to combine middle bins.
                                                Defaults to False.
  
      Returns:
          Tuple[List[List[float]], List[float]]: List of quantile thresholds and
                                                 estimated error bounds.
      """
  
      if len(errors) != len(uncertainties):
          raise ValueError(
              "Length of errors and uncertainties must be the same. errors is length %s and uncertainties is length %s"
              % (len(errors), len(uncertainties))
          )
  
      valid_types = {"quantile", "error-wise"}
      if type not in valid_types:
          raise ValueError(
              "results: type must be one of %r. " % valid_types
          )
  
      # Isotonically regress line
      ir = IsotonicRegression(out_of_bounds="clip", increasing=True)
  
      _ = ir.fit_transform(uncertainties, errors)
  
      uncert_boundaries = []
      estimated_errors = []
  
      # Estimate error bounds for each quantile bin
      if type == "quantile":
          quantiles = np.arange(1 / num_bins, 1, 1 / num_bins)[
              : num_bins - 1
          ]
          for q in range(len(quantiles)):
              q_conf_higher = [np.quantile(uncertainties, quantiles[q])]
              q_error_higher = ir.predict(q_conf_higher)
  
              estimated_errors.append(q_error_higher[0])
              uncert_boundaries.append(q_conf_higher)
  
      elif type == "error_wise":
          quantiles = np.arange(num_bins - 1)
          estimated_errors = [
              [(acceptable_thresh * x)] for x in quantiles
          ]
  
          uncert_boundaries = [
              (ir.predict(x)).tolist() for x in estimated_errors
          ]
          raise NotImplementedError(
              "error_wise Quantile Binning not implemented yet"
          )
  
      # IF combine bins, we grab only the values for the two outer bins
      if combine_middle_bins:
          estimated_errors = [estimated_errors[0], estimated_errors[-1]]
          uncert_boundaries = [
              uncert_boundaries[0],
              uncert_boundaries[-1],
          ]
  
      return uncert_boundaries, estimated_errors
  
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 2 for calling a global function with example usage: quantile_binning_and_est_errors(errors, uncertainties, num_bins, type, acceptable_thresh, combine_middle_bins) and returns: uncert_boundaries,  estimated_errors