code: def kde_partition_data(data, estimate_tails=True):
      
      kde = stats.kde.gaussian_kde(data)
      evaluation_bins = np.linspace(start=np.min(data) - (kde.covariance_factor() / 2),
                                    stop=np.max(data) +
                                    (kde.covariance_factor() / 2),
                                    num=np.floor(((np.max(data) - np.min(data)) / kde.covariance_factor()) + 1).astype(int))
      cdf_vals = [kde.integrate_box_1d(-np.inf, x) for x in evaluation_bins]
      evaluation_weights = np.diff(cdf_vals)
  
      if estimate_tails:
          bins = np.concatenate(([np.min(data) - (1.5 * kde.covariance_factor())],
                                 evaluation_bins,
                                 [np.max(data) + (1.5 * kde.covariance_factor())]))
      else:
          bins = np.concatenate(([-np.inf], evaluation_bins, [np.inf]))
  
      weights = np.concatenate(
          ([cdf_vals[0]], evaluation_weights, [1 - cdf_vals[-1]]))
  
      return {
          "bins": bins,
          "weights": weights
      }
docs: Convenience method for building a partition and weights using a gaussian Kernel Density Estimate and default bandwidth.
  
      Args:
          data (list-like): The data from which to construct the estimate
          estimate_tails (bool): Whether to estimate the tails of the distribution to keep the partition object finite
  
      Returns:
          A new partition_object::
  
          {
              "partition": (list) The endpoints of the partial partition of reals,
              "weights": (list) The densities of the bins implied by the partition.
          }