code: def _chain_stats(self, samples, mean=None, std=None, step=None):
      acceptance = acceptance_rate(samples)
      if mean is None:
          mean = np.mean(
              np.reshape(samples, (-1, samples.shape[2])), axis=0
          )
      if std is None:
          std = np.std(
              np.reshape(samples, (-1, samples.shape[2])), axis=0
          )
      ess = effective_sample_size(samples, mean, std)
      jump_distance = mean_jump_distance(samples)
      if samples.shape[0] > 1:
          grd = gelman_rubin_diagnostic(samples)
      if step is None:
          self.logger.info(
              "Acceptance [%5.4f] min ESS [%5.4f] max ESS [%5.4f] average jump [%5.4f]"
              % (acceptance, np.min(ess), np.max(ess), jump_distance)
          )
      else:
          self.logger.info(
              "Step [%d] acceptance [%5.4f] min ESS [%5.4f] max ESS [%5.4f] average jump [%5.4f]"
              % (
                  step,
                  acceptance,
                  np.min(ess),
                  np.max(ess),
                  jump_distance,
              )
          )
      return acceptance, ess, jump_distance
  
imports: from __future__ import print_function
  from __future__ import division
  import os
  import json
  import logging
  import time
  import torch
  import numpy
  from tqdm import tqdm
  import matplotlib.pyplot
  from nnest.trainer import Trainer
  from nnest.utils.evaluation import acceptance_rate, effective_sample_size, mean_jump_distance, gelman_rubin_diagnostic
  from nnest.utils.logger import create_logger, get_or_create_run_dir
label_desc: Use image node_id 5 for calling the Sampler obj's underlying member method code with example usage: obj._chain_stats(samples, mean, std, step) and returns: acceptance,  ess,  jump_distance