code: def _extract_graph_data_from_slicing_metrics(
      slicing_metrics: Sequence[tfma.view.SlicedMetrics],
      metric: str,
      slices_key: str = "",
      output_name: str = "",
      sub_key: str = "",
  ) -> Optional[graphics.Graph]:
      """Generates a barchart for a metric.
  
      Each bar in the barchart represents a slice in slicing_metrics. The size of
      a bar indicates the value of the metric for that slice.
  
      Args:
        slicing_metrics: A sequence of `tfma.view.SlicedMetrics` objects, where each
          `tfma.view.SlicedMetrics` corresponds to a different slice.
        metric: The name of a metric.
        slices_key: Only the slices with this slices_key will be added into graph.
          If it's an empty string, then all the the slices will be included.
        output_name: The output_name of interest in the slicing_metrics. '' by
          default.
        sub_key: The sub_key of interest in the slicing_metrics. '' by default.
  
      Returns:
        A Graph object, or None if any of the following are true:
          * metrics values format are not doubleValue or boundedValue.
          * the metric name ends with "_diff".
          * the metric name is "__ERROR__".
      """
      if metric.endswith("_diff") or metric == "__ERROR__":
          return None
  
      metric_values = []
      bounds = []
      slice_values = []
      has_bounded_value = False
      for slicing_metric in slicing_metrics:
          key, value = graphics.stringify_slice_key(slicing_metric[0])
          if key != "Overall" and slices_key and key != slices_key:
              continue
          slice_values.append(value)
  
          if (
              output_name not in slicing_metric[1]
              or sub_key not in slicing_metric[1][output_name]
              or metric not in slicing_metric[1][output_name][sub_key]
          ):
              logging.warning(
                  "%s, %s, %s not in %s. Skipping %s",
                  output_name,
                  sub_key,
                  metric,
                  slicing_metric[1],
                  slices_key,
              )
              return None
  
          # https://www.tensorflow.org/tfx/model_analysis/metrics#metric_value
          metric_value = slicing_metric[1][output_name][sub_key][metric]
          if "doubleValue" in metric_value:
              metric_values.append(metric_value["doubleValue"])
              bounds.append(
                  (
                      metric_value["doubleValue"],
                      metric_value["doubleValue"],
                  )
              )
          elif "boundedValue" in metric_value:
              has_bounded_value = True
              metric_values.append(
                  metric_value["boundedValue"]["value"]
              )
              bounds.append(
                  (
                      metric_value["boundedValue"]["lowerBound"],
                      metric_value["boundedValue"]["upperBound"],
                  )
              )
          else:
              logging.warning(
                  "%s must be a doubleValue or boundedValue; skipping %s.",
                  metric,
                  slices_key,
              )
              return None
  
      graph = graphics.Graph()
      graph.x = metric_values
      graph.y = slice_values
      if has_bounded_value:
          graph.xerr = [
              [
                  float(metric_value) - float(bound[0])
                  for metric_value, bound in zip(metric_values, bounds)
              ],
              [
                  float(bound[1]) - float(metric_value)
                  for metric_value, bound in zip(metric_values, bounds)
              ],
          ]
      graph.xlabel = metric
      graph.ylabel = "slices"
      graph.name = f"{metric} | {slices_key}" if slices_key else metric
      graph.title = f"{metric} | {slices_key}" if slices_key else metric
      graph.color = graphics._COLOR_PALETTE["material_purple_500"]
      return graph
  
file_path: model-card-toolkit/model_card_toolkit/utils/tf_graphics.py
imports: import logging
  from typing import Optional, Sequence, Union
  import tensorflow_model_analysis
  from tensorflow_metadata.proto.v0 import statistics_pb2
  from model_card_toolkit import model_card
  from model_card_toolkit.utils import graphics
label_desc: Use image node_id 4 for calling a global function with example usage: _extract_graph_data_from_slicing_metrics(slicing_metrics, metric, slices_key, output_name, sub_key) and returns: graph, None, None, None