code: def _class_split_viz(
      node: ShadowDecTreeNode,
      X_train: np.ndarray,
      y_train: np.ndarray,
      colors: dict,
      node_heights,
      filename: str,
      ticks_fontsize: int,
      label_fontsize: int,
      fontname: str,
      precision: int,
      histtype: ("bar", "barstacked", "strip"),
      X: np.array,
      highlight_node: bool,
  ):
      height_range = (0.5, 1.5)
      h = _prop_size(
          n=node_heights[node.id],
          counts=node_heights.values(),
          output_range=height_range,
      )
      figsize = (3.3, h)
      fig, ax = plt.subplots(1, 1, figsize=figsize)
  
      feature_name = node.feature_name()
  
      # Get X, y data for all samples associated with this node.
      X_feature = X_train[:, node.feature()]
      X_node_feature, y_train = (
          X_feature[node.samples()],
          y_train[node.samples()],
      )
  
      n_classes = node.shadow_tree.nclasses()
      nbins = _get_num_bins(histtype, n_classes)
  
      # for categorical splits, we need to ensure that each vertical bar will represent only one categorical feature value
      if node.is_categorical_split():
          feature_unique_size = np.unique(X_feature).size
          # keep the bar widths as uniform as possible for all node visualisations
          nbins = (
              nbins
              if nbins > feature_unique_size
              else feature_unique_size + 1
          )
  
      # only for str categorical features which are str type, int categorical features can work fine as numerical ones
      if node.is_categorical_split() and type(X_feature[0]) == str:
          # TODO think if the len() should be from all training[feature] data vs only data from this specific node ?
          overall_feature_range = (0, len(np.unique(X_feature)) - 1)
      else:
          overall_feature_range = (
              np.min(X_train[:, node.feature()]),
              np.max(X_train[:, node.feature()]),
          )
  
      bins = np.linspace(
          start=overall_feature_range[0],
          stop=overall_feature_range[1],
          num=nbins,
          endpoint=True,
      )
      _format_axes(
          ax,
          feature_name,
          None,
          colors,
          fontsize=label_fontsize,
          fontname=fontname,
          ticks_fontsize=ticks_fontsize,
          grid=False,
          pad_for_wedge=True,
      )
  
      class_names = node.shadow_tree.class_names
      class_values = node.shadow_tree.classes()
      X_hist = [X_node_feature[y_train == cl] for cl in class_values]
  
      # for multiclass examples, there could be scenarios where a node won't contain all the class value labels which will
      # generate a matplotlib exception. To solve this, we need to filter only the class values which belong to a node and
      # theirs corresponding colors.
      X_colors = [
          colors[cl]
          for i, cl in enumerate(class_values)
          if len(X_hist[i]) > 0
      ]
      X_hist = [hist for hist in X_hist if len(hist) > 0]
  
      if histtype == "strip":
          ax.yaxis.set_visible(False)
          ax.spines["left"].set_visible(False)
          sigma = 0.013
          mu = 0.05
          class_step = 0.08
          dot_w = 20
          ax.set_ylim(0, mu + n_classes * class_step)
          for i, bucket in enumerate(X_hist):
              alpha = (
                  colors["scatter_marker_alpha"]
                  if len(bucket) > 10
                  else 1
              )
              y_noise = np.random.normal(
                  mu + i * class_step, sigma, size=len(bucket)
              )
              ax.scatter(
                  bucket,
                  y_noise,
                  alpha=alpha,
                  marker="o",
                  s=dot_w,
                  c=colors[i],
                  edgecolors=colors["edge"],
                  lw=0.3,
              )
      else:
          hist, bins, barcontainers = ax.hist(
              X_hist,
              color=X_colors,
              align="mid",
              histtype=histtype,
              bins=bins,
              label=class_names,
          )
  
          # Alter appearance of each bar
          if isinstance(
              barcontainers[0], matplotlib.container.BarContainer
          ):
              for patch in barcontainers:
                  for rect in patch.patches:
                      rect.set_linewidth(0.5)
                      rect.set_edgecolor(colors["rect_edge"])
              ax.set_yticks([0, max([max(h) for h in hist])])
          elif isinstance(
              barcontainers[0], matplotlib.patches.Rectangle
          ):
              # In case a node will contains samples from only one class.
              for rect in barcontainers.patches:
                  rect.set_linewidth(0.5)
                  rect.set_edgecolor(colors["rect_edge"])
              ax.set_yticks([0, max(hist)])
  
      # set an empty space at the beginning and the end of the node visualisation for better clarity
      bin_length = bins[1] - bins[0]
      overall_feature_range_wide = (
          bins[0] - 2 * bin_length,
          bins[len(bins) - 1] + 2 * bin_length,
      )
  
      ax.set_xlim(*overall_feature_range_wide)
  
      if node.is_categorical_split() and type(X_feature[0]) == str:
          # run draw to refresh the figure to get the xticklabels
          plt.draw()
          node_split = list(map(str, node.split()))
          # get the label text and its position from the figure
          label_index = dict(
              [
                  (label.get_text(), label.get_position()[0])
                  for label in ax.get_xticklabels()
              ]
          )
          # get tick positions, ignoring "out of dictionary" symbol added by tensorflow trees for "unknown symbol"
          wedge_ticks_position = [
              label_index[split]
              for split in node_split
              if split in label_index
          ]
          wedge_ticks = _draw_wedge(
              ax,
              x=wedge_ticks_position,
              node=node,
              color=colors["wedge"],
              is_classifier=True,
              h=h,
              height_range=height_range,
              bins=bins,
          )
          if highlight_node:
              highlight_value = [label_index[X[node.feature()]]]
              _ = _draw_wedge(
                  ax,
                  x=highlight_value,
                  node=node,
                  color=colors["highlight"],
                  is_classifier=True,
                  h=h,
                  height_range=height_range,
                  bins=bins,
              )
      else:
          wedge_ticks = _draw_wedge(
              ax,
              x=node.split(),
              node=node,
              color=colors["wedge"],
              is_classifier=True,
              h=h,
              height_range=height_range,
              bins=bins,
          )
          if highlight_node:
              _ = _draw_wedge(
                  ax,
                  x=X[node.feature()],
                  node=node,
                  color=colors["highlight"],
                  is_classifier=True,
                  h=h,
                  height_range=height_range,
                  bins=bins,
              )
  
      _set_wedge_ticks(
          ax,
          ax_ticks=list(overall_feature_range),
          wedge_ticks=wedge_ticks,
      )
  
      if filename is not None:
          plt.savefig(filename, bbox_inches="tight", pad_inches=0)
          plt.close()
  
imports: import os
  import tempfile
  from typing import Mapping, List, Callable
  import matplotlib
  import matplotlib.patches
  import matplotlib.pyplot
  import numpy
  import pandas
  from colour import Color, rgb2hex
  from sklearn import tree
  from dtreeviz.colors import adjust_colors
  from dtreeviz.interpretation import explain_prediction_plain_english, explain_prediction_sklearn_default
  from dtreeviz.models.shadow_decision_tree import ShadowDecTree
  from dtreeviz.models.shadow_decision_tree import ShadowDecTreeNode
  from dtreeviz.utils import myround, DTreeVizRender, add_classifier_legend, _format_axes, _draw_wedge, _set_wedge_ticks, tessellate, is_numeric
label_desc: Use image node_id 1 for calling a global function with example usage: _class_split_viz(node, X_train, y_train, colors, node_heights, filename, ticks_fontsize, label_fontsize, fontname, precision, histtype, X, highlight_node) without return types