class_docstr: stats logging object useful for gathering statistics of training a deep net in pytorch
  Example::
  
      # init stats structure that logs statistics 'objective' and 'top1e'
      stats = Stats( ('objective','top1e') )
      network = init_net() # init a pytorch module (=nueral network)
      dataloader = init_dataloader() # init a dataloader
      for epoch in range(10):
          # start of epoch -> call new_epoch
          stats.new_epoch()
  
          # iterate over batches
          for batch in dataloader:
  
              output = network(batch) # run and save into a dict of output variables
  
              # stats.update() automatically parses the 'objective' and 'top1e' from
              # the "output" dict and stores this into the db
              stats.update(output)
              # prints the metric averages over given epoch
              std_out = stats.get_status_string()
              logger.info(str_out)
          # stores the training plots into '/tmp/epoch_stats.pdf'
          # and plots into a visdom server running at localhost (if running)
          stats.plot_stats(plot_file='/tmp/epoch_stats.pdf')
code: def synchronize_logged_vars(self, log_vars, default_val=float("NaN")):
      stat_sets = list(self.stats.keys())
  
      # remove the additional log_vars
      for stat_set in stat_sets:
          for stat in self.stats[stat_set].keys():
              if stat not in log_vars:
                  logger.warning(
                      f"additional stat {stat_set}:{stat} -> removing"
                  )
  
          self.stats[stat_set] = {
              stat: v
              for stat, v in self.stats[stat_set].items()
              if stat in log_vars
          }
  
      self.log_vars = log_vars  # !!!
  
      for stat_set in stat_sets:
          for stat in log_vars:
              if stat not in self.stats[stat_set]:
                  logger.info(
                      "missing stat %s:%s -> filling with default values (%1.2f)"
                      % (stat_set, stat, default_val)
                  )
              elif (
                  len(self.stats[stat_set][stat].history)
                  != self.epoch + 1
              ):
                  h = self.stats[stat_set][stat].history
                  if len(h) == 0:  # just never updated stat ... skip
                      continue
                  else:
                      logger.info(
                          "incomplete stat %s:%s -> reseting with default values (%1.2f)"
                          % (stat_set, stat, default_val)
                      )
              else:
                  continue
  
              self.stats[stat_set][stat] = AverageMeter()
              self.stats[stat_set][stat].reset()
  
              lastep = self.epoch + 1
              for ep in range(lastep):
                  self.stats[stat_set][stat].update(
                      default_val, n=1, epoch=ep
                  )
              epoch_generated = self.stats[stat_set][stat].get_epoch()
              assert (
                  epoch_generated == self.epoch + 1
              ), "bad epoch of synchronized log_var! %d vs %d" % (
                  self.epoch + 1,
                  epoch_generated,
              )
  
imports: import gzip
  import json
  import logging
  import time
  import warnings
  from collections.abc import Iterable
  from itertools import cycle
  import matplotlib
  import matplotlib.pyplot
  import numpy
  from matplotlib import colors
  from pytorch3d.implicitron.tools.vis_utils import get_visdom_connection
label_desc: Use image node_id 17 for calling the Stats obj's underlying member method code with example usage: obj.synchronize_logged_vars(log_vars, default_val) without return types