docstr: function to register finished runs
  
  Every time a run has finished, this function should be called
  to register it with the result logger. If overwritten, make
  sure to call this method from the base class to ensure proper
  logging.
  
  
  Parameters:
  -----------
  job_id: dict
      a dictionary containing all the info about the run
  job_result: dict
      contains all the results of the job, i.e. it's a dict with
      the keys 'loss' and 'info'
docstr_tok: ["function","to","register","finished","runs","Every","time","a","run","has","finished",",","this","function","should","be","called","to","register","it","with","the","result","logger",".","If","overwritten",",","make","sure","to","call","this","method","from","the","base","class","to","ensure","proper","logging",".","Parameters",":","--","--","--","--","--","-","job_id",":","dict","a","dictionary","containing","all","the","info","about","the","run","job_result",":","dict","contains","all","the","results","of","the","job",",","i.e",".","it","'s","a","dict","with","the","keys","'loss","'","and","'info","'"]
code: def new_result(self, job):
      """
      function to register finished runs
  
      Every time a run has finished, this function should be called
      to register it with the result logger. If overwritten, make
      sure to call this method from the base class to ensure proper
      logging.
  
  
      Parameters:
      -----------
      job_id: dict
          a dictionary containing all the info about the run
      job_result: dict
          contains all the results of the job, i.e. it's a dict with
          the keys 'loss' and 'info'
  
      """
      super().new_result(job)
  
      conf = ConfigSpace.Configuration(
          self.config_space, job.kwargs["config"]
      ).get_array()
  
      epochs = len(job.result["info"]["learning_curve"])
      budget = int(job.kwargs["budget"])
  
      t_idx = (
          np.linspace(budget / epochs, budget, epochs) / self.max_budget
      )
      x_new = np.repeat(conf[None, :], t_idx.shape[0], axis=0)
  
      x_new = np.concatenate((x_new, t_idx[:, None]), axis=1)
  
      # Smooth learning curve
      lc = smoothing(job.result["info"]["learning_curve"])
  
      # Flip learning curves since LC-Net wants increasing curves
      lc_new = [1 - y for y in lc]
  
      if self.train is None:
          self.train = x_new
          self.train_targets = lc_new
      else:
          self.train = np.append(self.train, x_new, axis=0)
          self.train_targets = np.append(
              self.train_targets, lc_new, axis=0
          )
  
      if self.counter >= self.n_points:
          self.lock.acquire()
          y_min = np.min(self.train_targets)
          y_max = np.max(self.train_targets)
  
          train_targets = (self.train_targets - y_min) / (y_max - y_min)
  
          self.model.train(self.train, train_targets)
          self.is_trained = True
          self.counter = 0
          self.lock.release()
  
      else:
          self.counter += epochs
  
file_path: HpBandSter/hpbandster/optimizers/config_generators/lcnet.py
imports: import ConfigSpace
  import numpy
  import threading
  from robo.models.lcnet import LCNet, get_lc_net
  from hpbandster.core.base_config_generator import base_config_generator
label_desc: Use image node_id 3 for calling the LCNetWrapper obj's underlying member method code with example usage: obj.new_result(job) without return types