class_docstr: SmartPlotter is a Bridge pattern decoupling plotting functions from SmartExplainer.
  The smartplotter class includes all the methods used to display graphics
  Each SmartPlotter method is easy to use from a Smart explainer object,
  just use the following syntax
  Attributes :
  explainer: object
      SmartExplainer instance to point to.
  Example
  --------
  >>> xpl.plot.my_plot_method(param=value)
class_docstr_tok: ["SmartPlotter","is","a","Bridge","pattern","decoupling","plotting","functions","from","SmartExplainer",".","The","smartplotter","class","includes","all","the","methods","used","to","display","graphics","Each","SmartPlotter","method","is","easy","to","use","from","a","Smart","explainer","object",",","just","use","the","following","syntax","Attributes",":","explainer",":","object","SmartExplainer","instance","to","point","to",".","Example","--","--","--","--",">",">",">","xpl.plot.my_plot_method","(","param=value",")"]
docstr: Plotly bar plot of local explainers
  Parameters
  ----------
  index_value:
      the index of row, used in title of local contribution plot
  var_dict: numpy array
      Unidimensional numpy array containing the features names for the observation of interest.
  x_val: numpy array
      Unidimensional numpy array containing the features values for the observation of interest.
  contrib: numpy array
      Unidimensional numpy array containing the contribution value for the observation of interest.
  yaxis_max_label: int (default: 12)
      Maximum number of variables to display labels on the y axis
  subtitle: string (default: None)
      subtitle to display
  width : Int (default: 900)
      Plotly figure - layout width
  height : Int (default: 550)
      Plotly figure - layout height
  file_name: string (optional)
      Specify the save path of html files. If it is not provided, no file will be saved.
  auto_open: bool (default=False)
      open automatically the plot
  zoom: bool (default=False)
      graph is currently zoomed
  Returns
  -------
  plotly bar plot
      A bar plot with selected contributions and
      associated feature values for one observation.
code: def plot_bar_chart(
      self,
      index_value,
      var_dict,
      x_val,
      contrib,
      yaxis_max_label=12,
      subtitle=None,
      width=900,
      height=550,
      file_name=None,
      auto_open=False,
      zoom=False,
  ):
      """
      Plotly bar plot of local explainers
      Parameters
      ----------
      index_value:
          the index of row, used in title of local contribution plot
      var_dict: numpy array
          Unidimensional numpy array containing the features names for the observation of interest.
      x_val: numpy array
          Unidimensional numpy array containing the features values for the observation of interest.
      contrib: numpy array
          Unidimensional numpy array containing the contribution value for the observation of interest.
      yaxis_max_label: int (default: 12)
          Maximum number of variables to display labels on the y axis
      subtitle: string (default: None)
          subtitle to display
      width : Int (default: 900)
          Plotly figure - layout width
      height : Int (default: 550)
          Plotly figure - layout height
      file_name: string (optional)
          Specify the save path of html files. If it is not provided, no file will be saved.
      auto_open: bool (default=False)
          open automatically the plot
      zoom: bool (default=False)
          graph is currently zoomed
      Returns
      -------
      plotly bar plot
          A bar plot with selected contributions and
          associated feature values for one observation.
      """
      if len(index_value) != 0:
          dict_t = copy.deepcopy(self._style_dict["dict_title"])
          topmargin = 80
          dict_xaxis = copy.deepcopy(self._style_dict["dict_xaxis"])
          dict_yaxis = copy.deepcopy(self._style_dict["dict_yaxis"])
          dict_local_plot_colors = copy.deepcopy(
              self._style_dict["dict_local_plot_colors"]
          )
          title = f"Local Explanation - Id: <b>{index_value[0]}</b>"
          # Add subtitle
          if subtitle:
              title += "<br><sup>" + subtitle + "</sup>"
              topmargin += 15
          dict_t["text"] = title
          dict_xaxis["text"] = "Contribution"
          dict_yaxis["text"] = None
  
          layout = go.Layout(
              barmode="group",
              template="none",
              width=width,
              height=height,
              title=dict_t,
              xaxis_title=dict_xaxis,
              yaxis_title=dict_yaxis,
              yaxis_type="category",
              hovermode="closest",
              margin={"l": 150, "r": 20, "t": topmargin, "b": 70},
          )
          bars = []
          for num, expl in enumerate(
              list(zip(var_dict, x_val, contrib))
          ):
              group_name = None
              if expl[1] == "":
                  ylabel = "<i>{}</i>".format(expl[0])
                  hoverlabel = "<b>{}</b>".format(expl[0])
              else:
                  # If bar is a group of features, hovertext includes the values of the features of the group
                  # And color changes
                  if (
                      self.explainer.features_groups is not None
                      and self.explainer.inv_features_dict.get(expl[0])
                      in self.explainer.features_groups.keys()
                      and len(index_value) > 0
                  ):
                      group_name = self.explainer.inv_features_dict.get(
                          expl[0]
                      )
                      feat_groups_values = self.explainer.x_init[
                          self.explainer.features_groups[group_name]
                      ].loc[index_value[0]]
                      hoverlabel = "<br />".join(
                          [
                              "<b>{} :</b>{}".format(
                                  add_line_break(
                                      self.explainer.features_dict.get(
                                          f_name, f_name
                                      ),
                                      40,
                                      maxlen=120,
                                  ),
                                  add_line_break(
                                      f_value, 40, maxlen=160
                                  ),
                              )
                              for f_name, f_value in feat_groups_values.to_dict().items()
                          ]
                      )
                  else:
                      hoverlabel = "<b>{} :</b><br />{}".format(
                          add_line_break(expl[0], 40, maxlen=120),
                          add_line_break(expl[1], 40, maxlen=160),
                      )
                  trunc_value = truncate_str(expl[0], 45)
                  if not zoom:
                      # Truncate value if length is upper than 30
                      trunc_new_value = (
                          trunc_value.replace(
                              trunc_value[24 : len(trunc_value) - 3],
                              "...",
                          )
                          if len(trunc_value) > 30
                          else trunc_value
                      )
                  else:
                      trunc_new_value = trunc_value
                  if len(contrib) <= yaxis_max_label and (
                      self.explainer.features_groups is None
                      # We don't want to display label values for t-sne projected values of groups of features.
                      or (
                          self.explainer.features_groups is not None
                          and self.explainer.inv_features_dict.get(
                              expl[0]
                          )
                          not in self.explainer.features_groups.keys()
                      )
                  ):
                      # ylabel is based on trunc_new_value
                      ylabel = "<b>{} :</b><br />{}".format(
                          trunc_new_value, truncate_str(expl[1], 45)
                      )
                  else:
                      ylabel = "<b>{}</b>".format(trunc_new_value)
              contrib_value = expl[2]
              # colors
              if contrib_value >= 0:
                  color = 1 if expl[1] != "" else 0
              else:
                  color = -1 if expl[1] != "" else -2
  
              # If the bar is a group of features we modify the color
              if group_name is not None:
                  bar_color = (
                      self._style_dict["featureimp_groups"][0]
                      if color == 1
                      else self._style_dict["featureimp_groups"][1]
                  )
              else:
                  bar_color = dict_local_plot_colors[color]["color"]
  
              barobj = go.Bar(
                  x=[contrib_value],
                  y=[ylabel],
                  customdata=[hoverlabel],
                  orientation="h",
                  marker=dict_local_plot_colors[color],
                  marker_color=bar_color,
                  showlegend=False,
                  hovertemplate="%{customdata}<br />Contribution: %{x:.4f}<extra></extra>",
              )
  
              bars.append([color, contrib_value, num, barobj])
  
          bars.sort()
          fig = go.Figure(data=[x[-1] for x in bars], layout=layout)
          fig.update_yaxes(dtick=1)
          fig.update_yaxes(automargin=True)
          # fig.update_xaxes(automargin=True)
  
          if file_name:
              plot(fig, filename=file_name, auto_open=auto_open)
      else:
          fig = go.Figure()
          fig.update_layout(
              xaxis={"visible": False},
              yaxis={"visible": False},
              annotations=[
                  {
                      "text": "Select a valid single sample to display<br />Local Explanation plot.",
                      "xref": "paper",
                      "yref": "paper",
                      "showarrow": False,
                      "font": {"size": 14},
                  }
              ],
          )
      return fig
  
imports: import warnings
  from numbers import Number
  import random
  import copy
  import math
  import numpy
  from scipy.optimize import fsolve
  import scipy.cluster.hierarchy
  import pandas
  from plotly import graph_objs
  import plotly.express
  from plotly.subplots import make_subplots
  from plotly.offline import plot
  from shapash.manipulation.select_lines import select_lines
  from shapash.manipulation.summarize import compute_features_import, project_feature_values_1d, compute_corr
  from shapash.utils.utils import add_line_break, truncate_str, compute_digit_number, add_text, maximum_difference_sort_value, compute_sorted_variables_interactions_list_indices, compute_top_correlations_features
  from shapash.webapp.utils.utils import round_to_k
  from shapash.style.style_utils import colors_loading, select_palette, define_style
label_desc: Use image node_id 9 for calling the SmartPlotter obj's underlying member method code with example usage: obj.plot_bar_chart(index_value, var_dict, x_val, contrib, yaxis_max_label, subtitle, width, height, file_name, auto_open, zoom) and returns: fig