code: def make_json_formatted_for_single_chart(
      mutant_features, inference_result_proto, index_to_mutate
  ):
      """Returns JSON formatted for a single mutant chart.
  
      Args:
        mutant_features: An iterable of `MutantFeatureValue`s representing the
          X-axis.
        inference_result_proto: A ClassificationResponse or RegressionResponse
          returned by Servo, representing the Y-axis.
          It contains one 'classification' or 'regression' for every Example that
          was sent for inference. The length of that field should be the same length
          of mutant_features.
        index_to_mutate: The index of the feature being mutated for this chart.
  
      Returns:
        A JSON-able dict for rendering a single mutant chart, parseable by
        `vz-line-chart` or `vz-bar-chart`.
      """
      x_label = "step"
      y_label = "scalar"
  
      if isinstance(
          inference_result_proto,
          classification_pb2.ClassificationResponse,
      ):
          # classification_label -> [{x_label: y_label:}]
          series = {}
  
          # ClassificationResponse has a separate probability for each label
          for idx, classification in enumerate(
              inference_result_proto.result.classifications
          ):
              # For each example to use for mutant inference, we create a copied example
              # with the feature in question changed to each possible mutant value. So
              # when we get the inferences back, we get num_examples*num_mutants
              # results. So, modding by len(mutant_features) allows us to correctly
              # lookup the mutant value for each inference.
              mutant_feature = mutant_features[
                  idx % len(mutant_features)
              ]
              for class_index, classification_class in enumerate(
                  classification.classes
              ):
                  # Fill in class index when labels are missing
                  if classification_class.label == "":
                      classification_class.label = str(class_index)
                  # Special case to not include the "0" class in binary classification.
                  # Since that just results in a chart that is symmetric around 0.5.
                  if (
                      len(classification.classes) == 2
                      and classification_class.label == "0"
                  ):
                      continue
                  key = classification_class.label
                  if index_to_mutate:
                      key += " (index %d)" % index_to_mutate
                  if not key in series:
                      series[key] = {}
                  mutant_val = ensure_not_binary(
                      mutant_feature.mutant_value
                  )
                  if not mutant_val in series[key]:
                      series[key][mutant_val] = []
                  series[key][mutant_val].append(
                      classification_class.score
                  )
  
          # Post-process points to have separate list for each class
          return_series = collections.defaultdict(list)
          for key, mutant_values in iteritems(series):
              for value, y_list in iteritems(mutant_values):
                  return_series[key].append(
                      {
                          x_label: value,
                          y_label: sum(y_list) / float(len(y_list)),
                      }
                  )
              return_series[key].sort(key=lambda p: p[x_label])
          return return_series
  
      elif isinstance(
          inference_result_proto, regression_pb2.RegressionResponse
      ):
          points = {}
  
          for idx, regression in enumerate(
              inference_result_proto.result.regressions
          ):
              # For each example to use for mutant inference, we create a copied example
              # with the feature in question changed to each possible mutant value. So
              # when we get the inferences back, we get num_examples*num_mutants
              # results. So, modding by len(mutant_features) allows us to correctly
              # lookup the mutant value for each inference.
              mutant_feature = mutant_features[
                  idx % len(mutant_features)
              ]
              mutant_val = ensure_not_binary(
                  mutant_feature.mutant_value
              )
              if not mutant_val in points:
                  points[mutant_val] = []
              points[mutant_val].append(regression.value)
          key = "value"
          if index_to_mutate != 0:
              key += " (index %d)" % index_to_mutate
          list_of_points = []
          for value, y_list in iteritems(points):
              list_of_points.append(
                  {
                      x_label: value,
                      y_label: sum(y_list) / float(len(y_list)),
                  }
              )
          list_of_points.sort(key=lambda p: p[x_label])
          return {key: list_of_points}
  
      else:
          raise NotImplementedError(
              "Only classification and regression implemented."
          )
  
imports: from __future__ import division
  from __future__ import print_function
  import collections
  import copy
  import json
  import math
  from absl import logging
  import numpy
  import tensorflow
  from google.protobuf import json_format
  from six import binary_type, string_types, integer_types
  from six import iteritems
  from six.moves import zip
  from inspect import signature
  from utils import common_utils
  from utils import platform_utils
  from tensorflow_serving.apis import classification_pb2
  from tensorflow_serving.apis import inference_pb2
  from tensorflow_serving.apis import regression_pb2
label_desc: Use image node_id 12 for calling a global function with example usage: make_json_formatted_for_single_chart(mutant_features, inference_result_proto, index_to_mutate) and returns: return_series, dict