text: """Copyright (c) Facebook, Inc. and its affiliates.
  All rights reserved.
  
  This source code is licensed under the license found in the
  LICENSE file in the root directory of this source tree.
  
  Portions of the source code are from the OLTR project which
  notice below and in LICENSE in the root directory of
  this source tree.
  
  Copyright (c) 2019, Zhongqi Miao
  All rights reserved.
  """
  
  import numpy as np
  import matplotlib.pyplot as plt
  import torch
  from sklearn.metrics import f1_score
  import torch.nn.functional as F
  import importlib
  import pdb
  
  def source_import(file_path):
      """This function imports python module directly from source code using importlib"""
      spec = importlib.util.spec_from_file_location('', file_path)
      module = importlib.util.module_from_spec(spec)
      spec.loader.exec_module(module)
      return module
  
  def batch_show(inp, title=None):
      """Imshow for Tensor."""
      inp = inp.numpy().transpose((1, 2, 0))
      mean = np.array([0.485, 0.456, 0.406])
      std = np.array([0.229, 0.224, 0.225])
      inp = std * inp + mean
      inp = np.clip(inp, 0, 1)
      plt.figure(figsize=(20,20))
      plt.imshow(inp)
      if title is not None:
          plt.title(title)
  
  def print_write(print_str, log_file):
      print(*print_str)
      if log_file is None:
          return
      with open(log_file, 'a') as f:
          print(*print_str, file=f)
  
  def init_weights(model, weights_path, caffe=False, classifier=False):  
      """Initialize weights"""
      print('Pretrained %s weights path: %s' % ('classifier' if classifier else 'feature model',
                                                weights_path))    
      weights = torch.load(weights_path)   
      if not classifier:
          if caffe:
              weights = {k: weights[k] if k in weights else model.state_dict()[k] 
                         for k in model.state_dict()}
          else:
              weights = weights['state_dict_best']['feat_model']
              weights = {k: weights['module.' + k] if 'module.' + k in weights else model.state_dict()[k] 
                         for k in model.state_dict()}
      else:      
          weights = weights['state_dict_best']['classifier']
          weights = {k: weights['module.fc.' + k] if 'module.fc.' + k in weights else model.state_dict()[k] 
                     for k in model.state_dict()}
      model.load_state_dict(weights)   
      return model
  
  def shot_acc (preds, labels, train_data, many_shot_thr=100, low_shot_thr=20, acc_per_cls=False):
      
      if isinstance(train_data, np.ndarray):
          training_labels = np.array(train_data).astype(int)
      else:
          training_labels = np.array(train_data.dataset.labels).astype(int)
  
      if isinstance(preds, torch.Tensor):
          preds = preds.detach().cpu().numpy()
          labels = labels.detach().cpu().numpy()
      elif isinstance(preds, np.ndarray):
          pass
      else:
          raise TypeError('Type ({}) of preds not supported'.format(type(preds)))
      train_class_count = []
      test_class_count = []
      class_correct = []
      for l in np.unique(labels):
          train_class_count.append(len(training_labels[training_labels == l]))
          test_class_count.append(len(labels[labels == l]))
          class_correct.append((preds[labels == l] == labels[labels == l]).sum())
  
      many_shot = []
      median_shot = []
      low_shot = []
      for i in range(len(train_class_count)):
          if train_class_count[i] > many_shot_thr:
              many_shot.append((class_correct[i] / test_class_count[i]))
          elif train_class_count[i] < low_shot_thr:
              low_shot.append((class_correct[i] / test_class_count[i]))
          else:
              median_shot.append((class_correct[i] / test_class_count[i]))    
   
      if len(many_shot) == 0:
          many_shot.append(0)
      if len(median_shot) == 0:
          median_shot.append(0)
      if len(low_shot) == 0:
          low_shot.append(0)
  
      if acc_per_cls:
          class_accs = [c / cnt for c, cnt in zip(class_correct, test_class_count)] 
          return np.mean(many_shot), np.mean(median_shot), np.mean(low_shot), class_accs
      else:
          return np.mean(many_shot), np.mean(median_shot), np.mean(low_shot)
  
  def weighted_shot_acc (preds, labels, ws, train_data, many_shot_thr=100, low_shot_thr=20):
      
      training_labels = np.array(train_data.dataset.labels).astype(int)
  
      if isinstance(preds, torch.Tensor):
          preds = preds.detach().cpu().numpy()
          labels = labels.detach().cpu().numpy()
      elif isinstance(preds, np.ndarray):
          pass
      else:
          raise TypeError('Type ({}) of preds not supported'.format(type(preds)))
      train_class_count = []
      test_class_count = []
      class_correct = []
      for l in np.unique(labels):
          train_class_count.append(len(training_labels[training_labels == l]))
          test_class_count.append(ws[labels==l].sum())
          class_correct.append(((preds[labels==l] == labels[labels==l]) * ws[labels==l]).sum())
  
      many_shot = []
      median_shot = []
      low_shot = []
      for i in range(len(train_class_count)):
          if train_class_count[i] > many_shot_thr:
              many_shot.append((class_correct[i] / test_class_count[i]))
          elif train_class_count[i] < low_shot_thr:
              low_shot.append((class_correct[i] / test_class_count[i]))
          else:
              median_shot.append((class_correct[i] / test_class_count[i]))          
      return np.mean(many_shot), np.mean(median_shot), np.mean(low_shot)
          
  def F_measure(preds, labels, openset=False, theta=None):
      
      if openset:
          # f1 score for openset evaluation
          true_pos = 0.
          false_pos = 0.
          false_neg = 0.
          
          for i in range(len(labels)):
              true_pos += 1 if preds[i] == labels[i] and labels[i] != -1 else 0
              false_pos += 1 if preds[i] != labels[i] and labels[i] != -1 and preds[i] != -1 else 0
              false_neg += 1 if preds[i] != labels[i] and labels[i] == -1 else 0
  
          precision = true_pos / (true_pos + false_pos)
          recall = true_pos / (true_pos + false_neg)
          return 2 * ((precision * recall) / (precision + recall + 1e-12))
      else:
          # Regular f1 score
          return f1_score(labels.detach().cpu().numpy(), preds.detach().cpu().numpy(), average='macro')
  
  def mic_acc_cal(preds, labels):
      if isinstance(labels, tuple):
          assert len(labels) == 3
          targets_a, targets_b, lam = labels
          acc_mic_top1 = (lam * preds.eq(targets_a.data).cpu().sum().float() \
                         + (1 - lam) * preds.eq(targets_b.data).cpu().sum().float()) / len(preds)
      else:
          acc_mic_top1 = (preds == labels).sum().item() / len(labels)
      return acc_mic_top1
  
  
  def weighted_mic_acc_cal(preds, labels, ws):
      acc_mic_top1 = ws[preds == labels].sum() / ws.sum()
      return acc_mic_top1
  
  def class_count (data):
      labels = np.array(data.dataset.labels)
      class_data_num = []
      for l in np.unique(labels):
          class_data_num.append(len(labels[labels == l]))
      return class_data_num
  
  # def dataset_dist (in_loader):
  
  #     """Example, dataset_dist(data['train'][0])"""
      
  #     label_list = np.array([x[1] for x in in_loader.dataset.samples])
  #     total_num = len(data_list)
  
  #     distribution = []
  #     for l in np.unique(label_list):
  #         distribution.append((l, len(label_list[label_list == l])/total_num))
          
  #     return distribution
  
  
  # New Added
  def torch2numpy(x):
      if isinstance(x, torch.Tensor):
          return x.detach().cpu().numpy()
      elif isinstance(x, (list, tuple)):
          return tuple([torch2numpy(xi) for xi in x])
      else:
          return x
  
  def logits2score(logits, labels):
      scores = F.softmax(logits, dim=1)
      score = scores.gather(1, labels.view(-1, 1))
      score = score.squeeze().cpu().numpy()
      return score
  
  
  def logits2entropy(logits):
      scores = F.softmax(logits, dim=1)
      scores = scores.cpu().numpy() + 1e-30
      ent = -scores * np.log(scores)
      ent = np.sum(ent, 1)
      return ent
  
  
  def logits2CE(logits, labels):
      scores = F.softmax(logits, dim=1)
      score = scores.gather(1, labels.view(-1, 1))
      score = score.squeeze().cpu().numpy() + 1e-30
      ce = -np.log(score)
      return ce
  
  
  def get_priority(ptype, logits, labels):
      if ptype == 'score':
          ws = 1 - logits2score(logits, labels)
      elif ptype == 'entropy':
          ws = logits2entropy(logits)
      elif ptype == 'CE':
          ws = logits2CE(logits, labels)
      
      return ws
  
  def get_value(oldv, newv):
      if newv is not None:
          return newv
      else:
          return oldv
  