class_docstr: An `EventAccumulator` takes an event generator, and accumulates the
  values.
  
  The `EventAccumulator` is intended to provide a convenient Python interface
  for loading Event data written during a TensorFlow run. TensorFlow writes out
  `Event` protobuf objects, which have a timestamp and step number, and often
  contain a `Summary`. Summaries can have different kinds of data like an image,
  a scalar value, or a histogram. The Summaries also have a tag, which we use to
  organize logically related data. The `EventAccumulator` supports retrieving
  the `Event` and `Summary` data by its tag.
  
  Calling `Tags()` gets a map from `tagType` (e.g. `'images'`,
  `'compressedHistograms'`, `'scalars'`, etc) to the associated tags for those
  data types. Then, various functional endpoints (eg
  `Accumulator.Scalars(tag)`) allow for the retrieval of all data
  associated with that tag.
  
  The `Reload()` method synchronously loads all of the data written so far.
  
  Histograms, audio, and images are very large, so storing all of them is not
  recommended.
  
  Fields:
    audios: A reservoir.Reservoir of audio summaries.
    compressed_histograms: A reservoir.Reservoir of compressed
        histogram summaries.
    histograms: A reservoir.Reservoir of histogram summaries.
    images: A reservoir.Reservoir of image summaries.
    most_recent_step: Step of last Event proto added. This should only
        be accessed from the thread that calls Reload. This is -1 if
        nothing has been loaded yet.
    most_recent_wall_time: Timestamp of last Event proto added. This is
        a float containing seconds from the UNIX epoch, or -1 if
        nothing has been loaded yet. This should only be accessed from
        the thread that calls Reload.
    path: A file path to a directory containing tf events files, or a single
        tf events file. The accumulator will load events from this path.
    scalars: A reservoir.Reservoir of scalar summaries.
    tensors: A reservoir.Reservoir of tensor summaries.
  
  @@Tensors
class_docstr_tok: ["An","`","EventAccumulator","`","takes","an","event","generator",",","and","accumulates","the","values",".","The","`","EventAccumulator","`","is","intended","to","provide","a","convenient","Python","interface","for","loading","Event","data","written","during","a","TensorFlow","run",".","TensorFlow","writes","out","`","Event","`","protobuf","objects",",","which","have","a","timestamp","and","step","number",",","and","often","contain","a","`","Summary","`",".","Summaries","can","have","different","kinds","of","data","like","an","image",",","a","scalar","value",",","or","a","histogram",".","The","Summaries","also","have","a","tag",",","which","we","use","to","organize","logically","related","data",".","The","`","EventAccumulator","`","supports","retrieving","the","`","Event","`","and","`","Summary","`","data","by","its","tag",".","Calling","`","Tags","(",")","`","gets","a","map","from","`","tagType","`","(","e.g",".","`","'images","'","`",",","`","'compressedHistograms","'","`",",","`","'scalars","'","`",",","etc",")","to","the","associated","tags","for","those","data","types",".","Then",",","various","functional","endpoints","(","eg","`","Accumulator.Scalars","(","tag",")","`",")","allow","for","the","retrieval","of","all","data","associated","with","that","tag",".","The","`","Reload","(",")","`","method","synchronously","loads","all","of","the","data","written","so","far",".","Histograms",",","audio",",","and","images","are","very","large",",","so","storing","all","of","them","is","not","recommended",".","Fields",":","audios",":","A","reservoir.Reservoir","of","audio","summaries",".","compressed_histograms",":","A","reservoir.Reservoir","of","compressed","histogram","summaries",".","histograms",":","A","reservoir.Reservoir","of","histogram","summaries",".","images",":","A","reservoir.Reservoir","of","image","summaries",".","most_recent_step",":","Step","of","last","Event","proto","added",".","This","should","only","be","accessed","from","the","thread","that","calls","Reload",".","This","is","-1","if","nothing","has","been","loaded","yet",".","most_recent_wall_time",":","Timestamp","of","last","Event","proto","added",".","This","is","a","float","containing","seconds","from","the","UNIX","epoch",",","or","-1","if","nothing","has","been","loaded","yet",".","This","should","only","be","accessed","from","the","thread","that","calls","Reload",".","path",":","A","file","path","to","a","directory","containing","tf","events","files",",","or","a","single","tf","events","file",".","The","accumulator","will","load","events","from","this","path",".","scalars",":","A","reservoir.Reservoir","of","scalar","summaries",".","tensors",":","A","reservoir.Reservoir","of","tensor","summaries",".","@","@","Tensors"]
docstr: Called whenever an event is loaded.
docstr_tok: ["Called","whenever","an","event","is","loaded","."]
code: def _ProcessEvent(self, event):
      """Called whenever an event is loaded."""
      if self._first_event_timestamp is None:
          self._first_event_timestamp = event.wall_time
  
      if event.HasField("source_metadata"):
          new_source_writer = event_util.GetSourceWriter(
              event.source_metadata
          )
          if (
              self._source_writer
              and self._source_writer != new_source_writer
          ):
              logger.info(
                  (
                      "Found new source writer for event.proto. "
                      "Old: {0}, New: {1}"
                  ).format(self._source_writer, new_source_writer)
              )
          self._source_writer = new_source_writer
  
      if event.HasField("file_version"):
          new_file_version = event_util.ParseFileVersion(
              event.file_version
          )
          if (
              self.file_version
              and self.file_version != new_file_version
          ):
              ## This should not happen.
              logger.warning(
                  (
                      "Found new file_version for event.proto. This will "
                      "affect purging logic for TensorFlow restarts. "
                      "Old: {0} New: {1}"
                  ).format(self.file_version, new_file_version)
              )
          self.file_version = new_file_version
  
      self._MaybePurgeOrphanedData(event)
  
      ## Process the event.
      # GraphDef and MetaGraphDef are handled in a special way:
      # If no graph_def Event is available, but a meta_graph_def is, and it
      # contains a graph_def, then use the meta_graph_def.graph_def as our graph.
      # If a graph_def Event is available, always prefer it to the graph_def
      # inside the meta_graph_def.
      if event.HasField("graph_def"):
          if self._graph is not None:
              logger.warning(
                  (
                      "Found more than one graph event per run, or there was "
                      "a metagraph containing a graph_def, as well as one or "
                      "more graph events.  Overwriting the graph with the "
                      "newest event."
                  )
              )
          self._graph = event.graph_def
          self._graph_from_metagraph = False
      elif event.HasField("meta_graph_def"):
          if self._meta_graph is not None:
              logger.warning(
                  (
                      "Found more than one metagraph event per run. "
                      "Overwriting the metagraph with the newest event."
                  )
              )
          self._meta_graph = event.meta_graph_def
          if self._graph is None or self._graph_from_metagraph:
              # We may have a graph_def in the metagraph.  If so, and no
              # graph_def is directly available, use this one instead.
              meta_graph = meta_graph_pb2.MetaGraphDef()
              meta_graph.ParseFromString(self._meta_graph)
              if meta_graph.graph_def:
                  if self._graph is not None:
                      logger.warning(
                          (
                              "Found multiple metagraphs containing graph_defs,"
                              "but did not find any graph events.  Overwriting the "
                              "graph with the newest metagraph version."
                          )
                      )
                  self._graph_from_metagraph = True
                  self._graph = meta_graph.graph_def.SerializeToString()
      elif event.HasField("tagged_run_metadata"):
          tag = event.tagged_run_metadata.tag
          if tag in self._tagged_metadata:
              logger.warning(
                  'Found more than one "run metadata" event with tag '
                  + tag
                  + ". Overwriting it with the newest event."
              )
          self._tagged_metadata[
              tag
          ] = event.tagged_run_metadata.run_metadata
      elif event.HasField("summary"):
          for value in event.summary.value:
              if value.HasField("metadata"):
                  tag = value.tag
                  # We only store the first instance of the metadata. This check
                  # is important: the `FileWriter` does strip metadata from all
                  # values except the first one per each tag, but a new
                  # `FileWriter` is created every time a training job stops and
                  # restarts. Hence, we must also ignore non-initial metadata in
                  # this logic.
                  if tag not in self.summary_metadata:
                      self.summary_metadata[tag] = value.metadata
                      plugin_data = value.metadata.plugin_data
                      if plugin_data.plugin_name:
                          self._plugin_to_tag_to_content[
                              plugin_data.plugin_name
                          ][tag] = plugin_data.content
                      else:
                          logger.warning(
                              (
                                  "This summary with tag %r is oddly not associated with a "
                                  "plugin."
                              ),
                              tag,
                          )
  
              for summary_type, summary_func in SUMMARY_TYPES.items():
                  if value.HasField(summary_type):
                      datum = getattr(value, summary_type)
                      tag = value.tag
                      if summary_type == "tensor" and not tag:
                          # This tensor summary was created using the old method that used
                          # plugin assets. We must still continue to support it.
                          tag = value.node_name
                      getattr(self, summary_func)(
                          tag, event.wall_time, event.step, datum
                      )
  
imports: import collections
  import dataclasses
  import threading
  from typing import Optional, Sequence, Tuple
  from tensorboard.backend.event_processing import directory_watcher
  from tensorboard.backend.event_processing import event_file_loader
  from tensorboard.backend.event_processing import event_util
  from tensorboard.backend.event_processing import io_wrapper
  from tensorboard.backend.event_processing import plugin_asset_util
  from tensorboard.backend.event_processing import reservoir
  from tensorboard.backend.event_processing import tag_types
  from tensorboard.compat.proto import config_pb2
  from tensorboard.compat.proto import event_pb2
  from tensorboard.compat.proto import graph_pb2
  from tensorboard.compat.proto import meta_graph_pb2
  from tensorboard.compat.proto import tensor_pb2
  from tensorboard.plugins.distribution import compressor
  from tensorboard.util import tb_logging
label_desc: Use image node_id 9 for calling the EventAccumulator obj's underlying member method code with example usage: obj._ProcessEvent(event) without return types