text: import json
  import torch
  import pandas as pd
  import model.esrgan as models
  import torchvision
  
  from pathlib import Path
  from itertools import repeat
  from collections import OrderedDict
  
  
  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
  
  
  def save_predictions_as_imgs(
      loader, model, folder="saved_images/", device="cuda"
  ):
      model.eval()
      for idx, (x, y) in enumerate(loader):
          x = x.to(device=device)
          with torch.no_grad():
              preds = torch.sigmoid(model(x))
              preds = (preds > 0.5).float()
          torchvision.utils.save_image(
              preds, f"{folder}/pred_{idx}.png"
          )
          torchvision.utils.save_image(y.unsqueeze(1), f"{folder}{idx}.png")
  
      model.train()
  
  
  def configure(arch, pretrained, logger):
      """Global profile.
      Args:
          :param logger:
          :param arch:
          :param pretrained:
      """
  
      # Create model
      if pretrained:
          logger.info(f"Using pre-trained model `{arch}`.")
          model = models.__dict__[arch](pretrained=True)
      else:
          logger.info(f"Creating model `{arch}`.")
          model = models.__dict__[arch]()
  
      return model
  
  
  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)