text: import json
  from collections import OrderedDict
  from itertools import repeat
  from pathlib import Path
  
  import pandas as pd
  import torch
  import torch
  import numpy as np
  import random
  
  ROOT_PATH = Path(__file__).absolute().resolve().parent.parent.parent
  
  
  def set_random_seed(seed=42):
      # fix random seeds for reproducibility
      torch.manual_seed(seed)
      torch.backends.cudnn.deterministic = True
      torch.backends.cudnn.benchmark = False
      np.random.seed(seed)
      random.seed(seed)
  
  
  def ensure_dir(dirname):
      dirname = Path(dirname)
      if not dirname.is_dir():
          dirname.mkdir(parents=True, exist_ok=False)
  
  
  def read_json(fname):
      fname = Path(fname)
      with fname.open("rt") as handle:
          return json.load(handle, object_hook=OrderedDict)
  
  
  def write_json(content, fname):
      fname = Path(fname)
      with fname.open("wt") as handle:
          json.dump(content, handle, indent=4, sort_keys=False)
  
  
  def inf_loop(data_loader):
      """wrapper function for endless data loader."""
      for loader in repeat(data_loader):
          yield from loader
  
  
  def prepare_device(n_gpu_use):
      """
      setup GPU device if available. get gpu device indices which are used for DataParallel
      """
      n_gpu = torch.cuda.device_count()
      if n_gpu_use > 0 and n_gpu == 0:
          print(
              "Warning: There's no GPU available on this machine,"
              "training will be performed on CPU."
          )
          n_gpu_use = 0
      if n_gpu_use > n_gpu:
          print(
              f"Warning: The number of GPU's configured to use is {n_gpu_use}, but only {n_gpu} are "
              "available on this machine."
          )
          n_gpu_use = n_gpu
      device = torch.device("cuda:0" if n_gpu_use > 0 else "cpu")
      list_ids = list(range(n_gpu_use))
      return device, list_ids
  
  
  class MetricTracker:
      def __init__(self, *keys, writer=None):
          self.writer = writer
          self._data = pd.DataFrame(index=keys, columns=["total", "counts", "average"])
          self.reset()
  
      def reset(self):
          for col in self._data.columns:
              self._data[col].values[:] = 0
  
      def update(self, key, value, n=1):
          # if self.writer is not None:
          #     self.writer.add_scalar(key, value)
          self._data.total[key] += value * n
          self._data.counts[key] += n
          self._data.average[key] = self._data.total[key] / self._data.counts[key]
  
      def avg(self, key):
          return self._data.average[key]
  
      def result(self):
          return dict(self._data.average)
  
      def keys(self):
          return self._data.total.keys()
  