code: def plot_heatmap(
      hist_values: list,
      hist_bins: list,
      date: list,
      x_label: str,
      hist_name,
      y_label: str,
      is_num: bool = False,
      is_ts: bool = False,
      cmap: str = "ylorrd",
      top: int = 20,
  ):
      """Create and plot heatmap of column values.
  
      Copyright Eskapade:
      Kindly taken from Eskapade package and then modified. Reference link:
      https://github.com/KaveIO/Eskapade/blob/master/python/eskapade/visualization/vis_utils.py#L397
      License: https://github.com/KaveIO/Eskapade-Core/blob/master/LICENSE
      Modifications copyright INGA WB.
  
      :param list hist_values: values of heatmap in a 2d numpy array =
      :param list hist_bins: bin labels/edges on y-axis
      :param list date: dates for x/time axis of heatmap
      :param str x_label: Label for heatmap x-axis
      :param list hist_names: list of histogram names. default is [].
      :param str y_label: Label for histogram y-axis. default is None.
      :param bool is_num: True if observable to plot is numeric. default is True.
      :param bool is_ts: True if observable to plot is a timestamp. default is False.
      :param int top: only print the top 20 characters of x-labels and y-labels. default is 20.
      :param cmap: the colormap for heatmap. default is ylorrd.
      :return: base64 encoded plot image
      :rtype: str
      """
      if hist_name and len(hist_name) == 0:
          raise ValueError("length of heatmap names is zero")
  
      assert hist_values is not None and len(
          hist_values
      ), "Heatmap bin values have not been set."
      assert hist_bins is not None and len(
          hist_bins
      ), "Heatmap binning has not been set."
  
      # basic attribute check: time stamps treated as numeric.
      if is_ts:
          is_num = True
  
      # plot numeric and time stamps
      if is_num:
          bin_edges = hist_bins
          bin_values = hist_values
          assert (
              len(bin_edges) == len(bin_values) + 1
          ), "bin edges (+ upper edge) and bin values have inconsistent lengths: {:d} vs {:d}. {}".format(
              len(bin_edges), len(bin_values), x_label
          )
          return ""
  
      # plot categories
      else:
          labels = hist_bins
          values = hist_values
          assert len(labels) == len(
              values
          ), f"labels and values have different array lengths: {len(labels):d} vs {len(values):d}. {x_label}"
  
          # plot histogram
          fig = px.imshow(
              values,
              labels={"x": "Time Bins", "y": x_label, "color": y_label},
              x=date,
              y=[xtick(lab, top) for lab in labels],
              color_continuous_scale=cmap,
              text_auto=".2f",
              aspect="equal",
          )
  
          # set label granularity
          if len(date) > 0:
              granularity = math.ceil(len(date) / 50)
              date = date[::granularity]
  
          fig.update_xaxes(tickvals=date, ticktext=date, tickangle=-90)
          fig.update_yaxes(ticks="outside")
          fig.update_layout(
              xaxis={"type": "category"},
              margin={"l": 40, "r": 10, "t": 0},
          )
          fig.update_coloraxes(
              colorbar_len=0.8, colorbar_ticks="outside"
          )
          plot = json.loads(fig.to_json())
  
      return {
          "name": hist_name,
          "type": "heatmap",
          "plot": plot["data"],
          "layout": plot["layout"],
      }
  
imports: from __future__ import annotations
  import datetime
  import json
  import logging
  import math
  import warnings
  from collections import defaultdict
  import numpy
  import pandas
  import plotly.express
  import plotly.graph_objects
  from popmon.resources import templates_env
label_desc: Use image node_id 11 for calling a global function with example usage: plot_heatmap(hist_values, hist_bins, date, x_label, hist_name, y_label, is_num, is_ts, cmap, top) and returns: dict, str