code: def heatmap(y, x, figure_size, **kwargs):
      if "color" in kwargs:
          color = kwargs["color"]
      else:
          color = [1] * len(x)
  
      palette = []
      n_colors = 256
      for i in range(0, 128):
          palette.append((0.85, (0.85 / 128) * i, (0.85 / 128) * i))
      for i in range(128, 256):
          palette.append(
              (
                  0.85 - 0.85 * (i - 128.0) / 128.0,
                  0.85 - 0.85 * (i - 128.0) / 128.0,
                  0.85,
              )
          )
  
      if "color_range" in kwargs:
          color_min, color_max = kwargs["color_range"]
      else:
          color_min, color_max = min(color), max(
              color
          )  # Range of values that will be mapped to the palette, i.e. min and max possible correlation
  
      def value_to_color(val):
          if color_min == color_max:
              return palette[-1]
          else:
              # For now, return "max positive" correlation color
              if val == CORRELATION_IDENTICAL:
                  return palette[(n_colors - 1)]
              if val == CORRELATION_ERROR:
                  return palette[(n_colors - 1)]
              val_position = float((val - color_min)) / (
                  color_max - color_min
              )  # position of value in the input range, relative to the length of the input range
              val_position = min(
                  max(val_position, 0), 1
              )  # bound the position betwen 0 and 1
              # LOG IT
              val_position = math.pow(val_position, 0.925)
              ind = int(
                  val_position * (n_colors - 1)
              )  # target index in the color palette
              return palette[ind]
  
      if "size" in kwargs:
          size = kwargs["size"]
      else:
          size = [1] * len(x)
  
      if "size_range" in kwargs:
          size_min, size_max = (
              kwargs["size_range"][0],
              kwargs["size_range"][1],
          )
      else:
          size_min, size_max = min(size), max(size)
  
      size_scale = kwargs.get("size_scale", 500)
  
      # Scale with num squares
      size_scale = size_scale / len(x)
  
      def value_to_size(val):
          if val == 0:
              return 0.0
          if val == abs(CORRELATION_IDENTICAL):
              return 1.0
          # TODO: Better/more intuitive display of correlation errors
          if val == abs(CORRELATION_ERROR):
              return 0.0
          if size_min == size_max:
              return 1 * size_scale
          else:
              val_position = (val - size_min) * 0.999 / (
                  size_max - size_min
              ) + 0.001  # position of value in the input range, relative to the length of the input range
              val_position = min(
                  max(val_position, 0), 1
              )  # bound the position betwen 0 and 1
              # LOG IT
              val_position = math.pow(val_position, 0.5)
              return val_position
              # val_position = int(val_position*2)+4
              # return int(size_scale)
              # return val_position * int(size_scale)
  
      def do_wrapping(label, length):
          return wrap_custom(label, ["_", "-"], length)
          # return '\n'.join(wrap(label, 15))
  
      wrap_x = 12  # at top/bottom
      wrap_y = 13
      if "x_order" in kwargs:
          x_names = [t for t in kwargs["x_order"]]
      else:
          x_names = [t for t in sorted(set([v for v in x]))]
      # Wrap to help avoid overflow
      x_names = [do_wrapping(label, wrap_x) for label in x_names]
  
      x_to_num = {p[1]: p[0] for p in enumerate(x_names)}
  
      if "y_order" in kwargs:
          y_names = [t for t in kwargs["y_order"]]
      else:
          y_names = [t for t in sorted(set([v for v in y]))]
      # Wrap to help avoid overflow
      y_names = [do_wrapping(label, wrap_y) for label in y_names]
  
      y_to_num = {p[1]: p[0] for p in enumerate(y_names)}
  
      figure, axs = plt.subplots(1, 1, figsize=figure_size)
  
      plot_grid = plt.GridSpec(
          1, 15, figure=figure
      )  # Setup a 1x10 grid
      # plot_grid = plt.GridSpec(1, 15, hspace=0.2, wspace=0.1, figure = f) # Setup a 1x10 grid
      ax = plt.subplot(
          plot_grid[:, :-1]
      )  # Use the left 14/15ths of the grid for the main plot
  
      marker = kwargs.get("marker", "s")
  
      kwargs_pass_on = {
          k: v
          for k, v in kwargs.items()
          if k
          not in [
              "color",
              "palette",
              "color_range",
              "size",
              "size_range",
              "size_scale",
              "marker",
              "x_order",
              "y_order",
          ]
      }
  
      ax.tick_params(labelbottom="on", labeltop="on")
      ax.set_xticks([v for k, v in x_to_num.items()])
      ax.set_xticklabels(
          [k for k in x_to_num],
          rotation=90,
          horizontalalignment="center",
          linespacing=0.8,
      )
      ax.set_yticks([v for k, v in y_to_num.items()])
      ax.set_yticklabels([k for k in y_to_num], linespacing=0.85)
  
      ax.grid(False, "major")
      ax.grid(True, "minor")
      ax.set_xticks([t + 0.5 for t in ax.get_xticks()], minor=True)
      ax.set_yticks([t + 0.5 for t in ax.get_yticks()], minor=True)
  
      ax.set_xlim([-0.5, max([v for v in x_to_num.values()]) + 0.5])
      ax.set_ylim([-0.5, max([v for v in y_to_num.values()]) + 0.5])
      ax.set_facecolor("#F1F1F1")
      # figure.show()
      # figure.savefig("ASSOCTEST")
      delta_in_pix = ax.transData.transform(
          (1, 1)
      ) - ax.transData.transform((0, 0))
  
      index = 0
      for cur_x, cur_y in zip(x, y):
          wrapped_x_name = do_wrapping(cur_x, wrap_x)
          wrapped_y_name = do_wrapping(cur_y, wrap_y)
          before_coordinate = np.array(
              ax.transData.transform(
                  (
                      x_to_num[wrapped_x_name] - 0.5,
                      y_to_num[wrapped_y_name] - 0.5,
                  )
              )
          )
          after_coordinate = np.array(
              ax.transData.transform(
                  (
                      x_to_num[wrapped_x_name] + 0.5,
                      y_to_num[wrapped_y_name] + 0.5,
                  )
              )
          )
          before_pixels = np.round(before_coordinate, 0)
          after_pixels = np.round(after_coordinate, 0)
          desired_fraction = value_to_size(size[index])
          if desired_fraction == 0.0:
              index = index + 1
              continue
          if (
              kwargs["dataframe_report"][cur_x]["type"]
              == FeatureType.TYPE_NUM
              and kwargs["dataframe_report"][cur_y]["type"]
              == FeatureType.TYPE_NUM
          ):
              use_rectangle = False
          else:
              use_rectangle = True
              # desired_fraction = desired_fraction / 0.707
          delta_in_pix = after_pixels - before_pixels
          gap = np.round((1.0 - desired_fraction) * delta_in_pix / 2, 0)
          start = before_pixels + gap[0]
          ending = after_pixels - gap[0]
          start[0] = start[0] + 1
          ending[1] = ending[1] - 1
          start_doc = ax.transData.inverted().transform(start)
          ending_doc = ax.transData.inverted().transform(ending)
          cur_size = ending_doc - start_doc
          # cur_size = 0.50
          # bottom_left = ax.transData.transform((x_to_num[cur_x]-0.5, y_to_num[cur_y]))
          # print(f"{bottom_left[0]}")
          if use_rectangle:
              cur_rect = patches.Rectangle(
                  (start_doc[0], start_doc[1]),
                  cur_size[0],
                  cur_size[1],
                  facecolor=value_to_color(color[index]),
                  antialiased=True,
              )
          else:
              cur_rect = patches.Circle(
                  (
                      start_doc[0] + cur_size[0] / 2,
                      start_doc[1] + cur_size[1] / 2,
                  ),
                  cur_size[1] / 2,
                  facecolor=value_to_color(color[index]),
                  antialiased=True,
              )
          cur_rect.set_antialiased(True)
          ax.add_patch(cur_rect)
          index = index + 1
      # ax.scatter(
      #     x=[x_to_num[v] for v in x],
      #     y=[y_to_num[v] for v in y],
      #     marker=marker,
      #     s=[value_to_size(v) for v in size],
      #     c=[value_to_color(v) for v in color],
      #     **kwargs_pass_on
      # )
  
      # Add color legend on the right side of the plot
      if color_min < color_max:
          ax = plt.subplot(
              plot_grid[:, -1]
          )  # Use the rightmost column of the plot
  
          col_x = [0] * len(palette)  # Fixed x coordinate for the bars
          bar_y = np.linspace(
              color_min, color_max, n_colors
          )  # y coordinates for each of the n_colors bars
          ax.set_ylim(-1, 1)
          bar_height = bar_y[1] - bar_y[0]
          ax.barh(
              y=bar_y,
              width=[5] * len(palette),  # Make bars 5 units wide
              left=col_x,  # Make bars start at 0
              height=bar_height,
              color=palette,
              linewidth=0,
          )
          ax.set_xlim(
              1, 2
          )  # Bars are going from 0 to 5, so lets crop the plot somewhere in the middle
          ax.grid(False)  # Hide grid
          ax.set_facecolor("white")  # Make background white
          ax.set_xticks([])  # Remove horizontal ticks
          ax.set_yticks(
              np.linspace(min(bar_y), max(bar_y), 3)
          )  # Show vertical ticks for min, middle and max
          ax.yaxis.tick_right()  # Show vertical ticks on the right
      return figure
  
file_path: sweetviz/sweetviz/graph_associations.py
imports: import math
  import numpy
  import pandas
  import matplotlib.pyplot
  from sweetviz.sv_types import FeatureType
  import sweetviz.graph
  from sweetviz.config import config
  import itertools
  import matplotlib.patches
  from textwrap import wrap
label_desc: Use image node_id 3 for calling a global function with example usage: heatmap(y, x, figure_size) and returns: figure, wrap_custom, palette, palette, int, int, int, unknown, val_position, palette, palette