code: def log_eval_summary(
      step: int,
      eval_metrics: Sequence[Dict[str, Tuple[float, int]]],
      extra_eval_summary: Optional[Dict[str, Any]] = None,
      summary_writer: Optional[Any] = None,
      metrics_normalizer_fn: Optional[
          Callable[
              [Dict[str, Tuple[float, int]], str], Dict[str, float]
          ]
      ] = None,
      prefix: str = "valid",
      key_separator: str = "_",
  ) -> Dict[str, float]:
      """Computes and logs eval metrics.
  
      Args:
        step: Current step.
        eval_metrics: Sequence of dictionaries of calculated metrics.
        extra_eval_summary: A dict containing summaries that are already ready to be
          logged, e.g. global metrics from eval set, like precision/recall.
        summary_writer: Summary writer object.
        metrics_normalizer_fn: Used for normalizing metrics. The api for
          this function is: `new_metrics_dict = metrics_normalizer_fn( metrics_dict,
            split)`. If set to None, we use the normalize_metrics_summary which uses
            the normalizer paired with each metric to normalize it.
        prefix: str; Prefix added to the name of the summaries writen by this
          function.
        key_separator: Separator added between the prefix and key.
  
      Returns:
        eval summary: A dictionary of metrics.
      """
      eval_metrics = train_utils.stack_forest(eval_metrics)
  
      # Compute the sum over all examples in all batches.
      eval_metrics_summary = jax.tree_util.tree_map(
          lambda x: x.sum(), eval_metrics
      )
      # Normalize metrics by the total number of exampels.
      metrics_normalizer_fn = (
          metrics_normalizer_fn or train_utils.normalize_metrics_summary
      )
      eval_metrics_summary = metrics_normalizer_fn(
          eval_metrics_summary, "eval"
      )
      # If None, set to an empty dictionary.
      extra_eval_summary = extra_eval_summary or {}
  
      if jax.process_index() == 0:
          message = ""
          for key, val in eval_metrics_summary.items():
              message += f"{key}: {val} | "
          for key, val in extra_eval_summary.items():
              message += f"{key}: {val} | "
          logging.info("step: %d -- %s -- {%s}", step, prefix, message)
  
          if summary_writer is not None:
              for key, val in eval_metrics_summary.items():
                  summary_writer.scalar(
                      f"{prefix}{key_separator}{key}", val, step
                  )
              for key, val in extra_eval_summary.items():
                  summary_writer.scalar(
                      f"{prefix}{key_separator}{key}", val, step
                  )
              summary_writer.flush()
  
      # Add extra_eval_summary to the returned eval_summary.
      eval_metrics_summary.update(extra_eval_summary)
      return eval_metrics_summary
  
file_path: scenic/scenic/projects/vivit/evaluation_lib.py
imports: import os
  from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union
  from absl import logging
  import flax
  from flax.metrics import tensorboard
  from flax.training import checkpoints
  import jax
  import jax.numpy
  import numpy
  from scenic.train_lib_deprecated import pretrain_utils
  from scenic.train_lib_deprecated import train_utils
  from sklearn.metrics import average_precision_score
  from tensorflow.io import gfile
label_desc: Use image node_id 5 for calling a global function with example usage: log_eval_summary(step, eval_metrics, extra_eval_summary, summary_writer, metrics_normalizer_fn, prefix, key_separator) and returns: eval_metrics_summary