class_docstr: Complements the event system by providing aggregation functionality. How the events are aggregated
  is specified by the event interface decorators (see event_decorators.py).
  
  Note that the statistics calculation for episode aggregators will automatically be
  triggered on every `increment_log_step()` call.
class_docstr_tok: ["Complements","the","event","system","by","providing","aggregation","functionality",".","How","the","events","are","aggregated","is","specified","by","the","event","interface","decorators","(","see","event_decorators.py",")",".","Note","that","the","statistics","calculation","for","episode","aggregators","will","automatically","be","triggered","on","every","`","increment_log_step","(",")","`","call","."]
docstr: Constructor
  
  :param level: The aggregation level of this object, supported values:
                LogStatsLevel.STEP, LogStatsLevel.EPISODE, LogStatsLevel.EPOCH.
  :param consumers: Optionally an arbitrary number of consumers can be passed (a consumer being either
                    the downstream aggregator or a log writer)
docstr_tok: ["Constructor",":","param","level",":","The","aggregation","level","of","this","object",",","supported","values",":","LogStatsLevel.STEP",",","LogStatsLevel.EPISODE",",","LogStatsLevel.EPOCH",".",":","param","consumers",":","Optionally","an","arbitrary","number","of","consumers","can","be","passed","(","a","consumer","being","either","the","downstream","aggregator","or","a","log","writer",")"]
code: def __init__(
      self, level: LogStatsLevel, *consumers: LogStatsConsumer
  ):
      """
      Constructor
  
      :param level: The aggregation level of this object, supported values:
                    LogStatsLevel.STEP, LogStatsLevel.EPISODE, LogStatsLevel.EPOCH.
      :param consumers: Optionally an arbitrary number of consumers can be passed (a consumer being either
                        the downstream aggregator or a log writer)
      """
      self.level = level
      self.consumers = list(consumers)
  
      self.input: Dict[LogStatsKey, list] = defaultdict(list)
  
      self.last_stats: Optional[LogStats] = None
      """keep track of the previous statistics, required e.g. for cumulative statistics"""
  
      self.last_stats_step: Optional[int] = None
      """step number of the last statistics calculation"""
  
      self.cumulative_stats = dict()
      """keep track of all cumulative stats, required e.g. for an epoch where the previous epoch did not finish any 
          episode"""
  
      if level == LogStatsLevel.EPOCH:
          GlobalLogState.hook_on_log_step.append(self._hook_on_log_step)
  
imports: from abc import ABC, abstractmethod
  from collections import defaultdict
  from enum import Enum
  from typing import Union, Callable, Dict, Optional, NamedTuple, List, Type, TypeVar, Tuple, Any
  import numpy
  from maze.core.events.event_record import EventRecord
  from maze.core.events.event_topic_factory import event_topic_factory
label_desc: Use image node_id 1 to create a new LogStatsAggregator object from inherited base classes: LogStatsConsumer with example: obj = LogStatsAggregator(level)