code: def log_eval_summary(
      step: int,
      *,
      writer: metric_writers.MetricWriter,
      eval_metrics: Sequence[Dict[str, Tuple[float, int]]],
      extra_eval_summary: Optional[Mapping[str, float]] = None,
      metrics_normalizer_fn: Optional[
          Callable[
              [Dict[str, Tuple[float, int]], str], Dict[str, float]
          ]
      ] = None,
      prefix: str = "valid",
      key_separator: str = "_",
      flush_writer: bool = True,
  ) -> Dict[str, float]:
      """Computes and logs eval metrics.
  
      Args:
        step: Current step.
        writer: Metric writer object.
        eval_metrics: List of dictionaries of calculated metrics. Usually the
          sequence is the concatenation of the per-eval-step metrics, and every
          dictionary maps a metric name to an array of (value, normalizer) - where
          the array index is usually the batch index.
        extra_eval_summary: A dict containing summaries that are already ready to be
          logged, e.g. global metrics from eval set, like precision/recall.
        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 (after summing both
          metric and normalizer values).
        prefix: str; Prefix added to the name of the summaries writen by this
          function.
        key_separator: Separator added between the prefix and key.
        flush_writer: If True, flush the writer after logging.
  
      Returns:
        A dictionary of metrics, mapping both `eval_metrics` and
        `extra_eval_summary` from metric name (incl. `prefix`) to float value.
      """
      eval_metrics = 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 examples.
      metrics_normalizer_fn = (
          metrics_normalizer_fn or 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 {}
  
      # Adds extra_eval_summary to the returned eval_summary.
      eval_metrics_summary.update(extra_eval_summary)
  
      writer.write_scalars(
          step,
          {
              key_separator.join((prefix, key)): val
              for key, val in eval_metrics_summary.items()
          },
      )
  
      if flush_writer:
          writer.flush()
      return eval_metrics_summary
  
imports: import collections.abc
  import copy
  import functools
  import os
  import re
  import time
  from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, Union
  from absl import logging
  from clu import metric_writers
  import flax
  from flax import jax_utils
  from flax import struct
  import flax.linen
  from flax.training import checkpoints
  import jax
  import jax.numpy
  import ml_collections
  import numpy
  import optax
  from scenic.common_lib import debug_utils
  from scenic.dataset_lib import dataset_utils
  from scenic.dataset_lib import datasets
  from scenic.train_lib import optimizers
  from tensorflow.io import gfile
label_desc: Use image node_id 18 for calling a global function with example usage: log_eval_summary(step) and returns: eval_metrics_summary