code: def resume_from_similar_file(
      log_dir,
      x_dim,
      loglikelihood,
      transform,
      max_tau=0,
      verbose=False,
      ndraw=400,
  ):
      """
      Change a stored UltraNest run to a modified loglikelihood/transform.
  
      Parameters
      ----------
      log_dir: str
          Folder containing results
      x_dim: int
          number of dimensions
      loglikelihood: function
          new likelihood function
      transform: function
          new transform function
      verbose: bool
          show progress
      ndraw: int
          set to >1 if functions can take advantage of vectorized computations
      max_tau: float
          Allowed dissimilarity in the live point ordering, quantified as
          normalised Kendall tau distance.
  
          max_tau=0 is the very conservative choice of stopping the warm start
          when the live point order differs.
          Near 1 are completely different live point orderings.
          Values in between permit mild disorder.
  
      Returns
      ----------
      sequence: dict
          contains arrays storing for each iteration estimates of:
  
              * logz: log evidence estimate
              * logzerr: log evidence uncertainty estimate
              * logvol: log volume estimate
              * samples_n: number of live points
              * logwt: log weight
              * logl: log likelihood
  
      final: dict
          same as ReactiveNestedSampler.results and
          ReactiveNestedSampler.run return values
  
      """
      import h5py
  
      filepath = os.path.join(log_dir, "results", "points.hdf5")
      filepath2 = os.path.join(log_dir, "results", "points.hdf5.new")
      fileobj = h5py.File(filepath, "r")
      _, ncols = fileobj["points"].shape
      num_params = ncols - 3 - x_dim
  
      points = fileobj["points"][:]
      fileobj.close()
      del fileobj
  
      pointstore2 = HDF5PointStore(filepath2, ncols, mode="w")
      stack = list(enumerate(points))
  
      pointpile = PointPile(x_dim, num_params)
      pointpile2 = PointPile(x_dim, num_params)
  
      def pop(Lmin):
          """Find matching sample from points file."""
          # look forward to see if there is an exact match
          # if we do not use the exact matches
          #   this causes a shift in the loglikelihoods
          for i, (idx, next_row) in enumerate(stack):
              row_Lmin = next_row[0]
              L = next_row[1]
              if row_Lmin <= Lmin and L > Lmin:
                  idx, row = stack.pop(i)
                  return idx, row
          return None, None
  
      roots = []
      roots2 = []
      initial_points_u = []
      initial_points_v = []
      initial_points_logl = []
      while True:
          _, row = pop(-np.inf)
          if row is None:
              break
          logl = row[1]
          u = row[3 : 3 + x_dim]
          v = row[3 + x_dim : 3 + x_dim + num_params]
          initial_points_u.append(u)
          initial_points_v.append(v)
          initial_points_logl.append(logl)
  
      v2 = transform(np.array(initial_points_u, ndmin=2, dtype=float))
      assert np.allclose(
          v2, initial_points_v
      ), "transform inconsistent, cannot resume"
      logls_new = loglikelihood(v2)
  
      for u, v, logl, logl_new in zip(
          initial_points_u,
          initial_points_v,
          initial_points_logl,
          logls_new,
      ):
          roots.append(pointpile.make_node(logl, u, v))
          roots2.append(pointpile2.make_node(logl_new, u, v))
          pointstore2.add(_listify([-np.inf, logl_new, 0.0], u, v), 1)
  
      batchsize = ndraw
      explorer = BreadthFirstIterator(roots)
      explorer2 = BreadthFirstIterator(roots2)
      main_iterator2 = SingleCounter()
      main_iterator2.Lmax = logls_new.max()
      good_state = True
  
      indices1, indices2 = np.meshgrid(
          np.arange(len(logls_new)), np.arange(len(logls_new))
      )
      last_good_like = -1e300
      last_good_state = 0
      epsilon = 1 + 1e-6
      niter = 0
      for batch in _explore_iterator_batch(
          explorer,
          pop,
          x_dim,
          num_params,
          pointpile,
          batchsize=batchsize,
      ):
          assert len(batch) > 0
          batch_u = np.array(
              [u for _, _, children in batch for u, _, _ in children],
              ndmin=2,
              dtype=float,
          )
          if batch_u.size > 0:
              assert batch_u.shape[1] == x_dim, batch_u.shape
              batch_v = np.array(
                  [
                      v
                      for _, _, children in batch
                      for _, v, _ in children
                  ],
                  ndmin=2,
                  dtype=float,
              )
              # print("calling likelihood with %d points" % len(batch_u))
              v2 = transform(batch_u)
              assert batch_v.shape[1] == num_params, batch_v.shape
              assert np.allclose(
                  v2, batch_v
              ), "transform inconsistent, cannot resume"
              logls_new = loglikelihood(batch_v)
          else:
              # no new points
              logls_new = []
  
          j = 0
          for Lmin, active_values, children in batch:
              next_node2 = explorer2.next_node()
              (
                  rootid2,
                  node2,
                  (active_nodes2, _, active_values2, _),
              ) = next_node2
              Lmin2 = float(node2.value)
  
              # in the tails of distributions it can happen that two points are out of order
              # but that may not be very important
              # in the interest of practicality, we allow this and only stop the
              # warmstart copying when some bulk of points differ.
              # in any case, warmstart should not be considered safe, but help iterating
              # and a final clean run is needed to finalise the results.
              if len(active_values) != len(active_values2):
                  if verbose == 2:
                      print(
                          "stopping, number of live points differ (%d vs %d)"
                          % (len(active_values), len(active_values2))
                      )
                      good_state = False
                  break
  
              if len(active_values) != len(indices1):
                  indices1, indices2 = np.meshgrid(
                      np.arange(len(active_values)),
                      np.arange(len(active_values2)),
                  )
              tau = normalised_kendall_tau_distance(
                  active_values, active_values2, indices1, indices2
              )
              order_consistent = tau <= max_tau
              if (
                  order_consistent
                  and len(active_values) > 10
                  and len(active_values) > 10
              ):
                  good_state = True
              elif not order_consistent:
                  good_state = False
              else:
                  # maintain state
                  pass
              if verbose == 2:
                  print(niter, tau)
              if good_state:
                  # print("        (%.1e)   L=%.1f" % (last_good_like, Lmin2))
                  # assert last_good_like < Lmin2, (last_good_like, Lmin2)
                  last_good_like = Lmin2
                  last_good_state = niter
              else:
                  # interpolate a increasing likelihood
                  # in the hope that the step size is smaller than
                  # the likelihood increase
                  Lmin2 = last_good_like
                  node2.value = Lmin2
                  last_good_like = last_good_like * epsilon
                  break
  
              for u, v, logl_old in children:
                  logl_new = logls_new[j]
                  j += 1
  
                  # print(j, Lmin2, '->', logl_new, 'instead of', Lmin, '->', [c.value for c in node2.children])
                  child2 = pointpile2.make_node(logl_new, u, v)
                  node2.children.append(child2)
                  if logl_new > Lmin2:
                      pointstore2.add(
                          _listify([Lmin2, logl_new, 0.0], u, v), 1
                      )
                  else:
                      if verbose == 2:
                          print(
                              "cannot use new point because it would decrease likelihood (%.1f->%.1f)"
                              % (Lmin2, logl_new)
                          )
                      # good_state = False
                      # break
  
              main_iterator2.passing_node(node2, active_nodes2)
  
              niter += 1
              if verbose:
                  sys.stderr.write("%d...\r" % niter)
  
              explorer2.expand_children_of(rootid2, node2)
  
          if not good_state:
              break
          if (
              main_iterator2.logZremain < main_iterator2.logZ
              and not good_state
          ):
              # stop as the results diverged already
              break
  
      if verbose:
          sys.stderr.write(
              "%d/%d iterations salvaged (%.2f%%).\n"
              % (
                  last_good_state + 1,
                  len(points),
                  (last_good_state + 1) * 100.0 / len(points),
              )
          )
      # delete the ones at the end from last_good_state onwards
      # assert len(pointstore2.fileobj['points']) == niter, (len(pointstore2.fileobj['points']), niter)
      mask = pointstore2.fileobj["points"][:, 0] <= last_good_like
      points2 = pointstore2.fileobj["points"][:][mask, :]
      del pointstore2.fileobj["points"]
      pointstore2.fileobj.create_dataset(
          "points",
          dtype=np.float64,
          shape=(0, pointstore2.ncols),
          maxshape=(None, pointstore2.ncols),
      )
      pointstore2.fileobj["points"].resize(len(points2), axis=0)
      pointstore2.fileobj["points"][:] = points2
      pointstore2.close()
      del pointstore2
  
      os.replace(filepath2, filepath)
  
imports: from __future__ import print_function, division
  import os
  import sys
  import csv
  import json
  import operator
  import time
  import warnings
  from numpy import log, exp, logaddexp
  import numpy
  from .utils import create_logger, make_run_dir, resample_equal, vol_prefactor, vectorize, listify
  from .utils import is_affine_transform, normalised_kendall_tau_distance, distributed_work_chunk_size
  from ultranest.mlfriends import MLFriends, AffineLayer, ScalingLayer, find_nearby, WrappingEllipsoid, RobustEllipsoidRegion
  from .store import HDF5PointStore, TextPointStore, NullPointStore
  from .viz import get_default_viz_callback
  from .ordertest import UniformOrderAccumulator
  from .netiter import PointPile, SingleCounter, MultiCounter, BreadthFirstIterator, TreeNode, count_tree_between, find_nodes_before, logz_sequence
  from .netiter import dump_tree, combine_results
  from .hotstart import get_auxiliary_contbox_parameterization
label_desc: Use image node_id 4 for calling a global function with example usage: resume_from_similar_file(log_dir, x_dim, loglikelihood, transform, max_tau, verbose, ndraw) and returns: None,  None, idx,  row