class_docstr: A sampler for continuous variables based on Hamiltonian mechanics.
  
  NUTS automatically tunes the step size and the number of steps per
  sample. A detailed description can be found at [1], "Algorithm 6:
  Efficient No-U-Turn Sampler with Dual Averaging".
  
  NUTS provides a number of statistics that can be accessed with
  `trace.get_sampler_stats`:
  
  - `mean_tree_accept`: The mean acceptance probability for the tree
    that generated this sample. The mean of these values across all
    samples but the burn-in should be approximately `target_accept`
    (the default for this is 0.8).
  - `diverging`: Whether the trajectory for this sample diverged. If
    there are any divergences after burnin, this indicates that
    the results might not be reliable. Reparametrization can
    often help, but you can also try to increase `target_accept` to
    something like 0.9 or 0.95.
  - `energy`: The energy at the point in phase-space where the sample
    was accepted. This can be used to identify posteriors with
    problematically long tails. See below for an example.
  - `energy_change`: The difference in energy between the start and
    the end of the trajectory. For a perfect integrator this would
    always be zero.
  - `max_energy_change`: The maximum difference in energy along the
    whole trajectory.
  - `depth`: The depth of the tree that was used to generate this sample
  - `tree_size`: The number of leafs of the sampling tree, when the
    sample was accepted. This is usually a bit less than
    `2 ** depth`. If the tree size is large, the sampler is
    using a lot of leapfrog steps to find the next sample. This can for
    example happen if there are strong correlations in the posterior,
    if the posterior has long tails, if there are regions of high
    curvature ("funnels"), or if the variance estimates in the mass
    matrix are inaccurate. Reparametrisation of the model or estimating
    the posterior variances from past samples might help.
  - `tune`: This is `True`, if step size adaptation was turned on when
    this sample was generated.
  - `step_size`: The step size used for this sample.
  - `step_size_bar`: The current best known step-size. After the tuning
    samples, the step size is set to this value. This should converge
    during tuning.
  - `model_logp`: The model log-likelihood for this sample.
  - `process_time_diff`: The time it took to draw the sample, as defined
    by the python standard library `time.process_time`. This counts all
    the CPU time, including worker processes in BLAS and OpenMP.
  - `perf_counter_diff`: The time it took to draw the sample, as defined
    by the python standard library `time.perf_counter` (wall time).
  - `perf_counter_start`: The value of `time.perf_counter` at the beginning
    of the computation of the draw.
  - `index_in_trajectory`: This is usually only interesting for debugging
    purposes. This indicates the position of the posterior draw in the
    trajectory. Eg a -4 would indicate that the draw was the result of the
    fourth leapfrog step in negative direction.
  - `largest_eigval` and `smallest_eigval`: Experimental statistics for
    some mass matrix adaptation algorithms. This is nan if it is not used.
  
  References
  ----------
  .. [1] Hoffman, Matthew D., & Gelman, Andrew. (2011). The No-U-Turn
     Sampler: Adaptively Setting Path Lengths in Hamiltonian Monte Carlo.
code: def _hamiltonian_step(self, start, p0, step_size):
      if self.tune and self.iter_count < 200:
          max_treedepth = self.early_max_treedepth
      else:
          max_treedepth = self.max_treedepth
  
      tree = _Tree(
          len(p0), self.integrator, start, step_size, self.Emax
      )
  
      reached_max_treedepth = False
      for _ in range(max_treedepth):
          direction = logbern(np.log(0.5)) * 2 - 1
          divergence_info, turning = tree.extend(direction)
  
          if divergence_info or turning:
              break
      else:
          reached_max_treedepth = not self.tune
  
      stats = tree.stats()
      accept_stat = stats["mean_tree_accept"]
      stats["reached_max_treedepth"] = reached_max_treedepth
      return HMCStepData(
          tree.proposal, accept_stat, divergence_info, stats
      )
  
imports: from __future__ import annotations
  from collections import namedtuple
  import numpy
  from pymc.math import logbern
  from pymc.pytensorf import floatX
  from pymc.stats.convergence import SamplerWarning
  from pymc.step_methods.compound import Competence
  from pymc.step_methods.hmc import integration
  from pymc.step_methods.hmc.base_hmc import BaseHMC, DivergenceInfo, HMCStepData
  from pymc.step_methods.hmc.integration import IntegrationError, State
  from pymc.vartypes import continuous_types
label_desc: Use image node_id 2 for calling the NUTS obj's underlying member method code with example usage: obj._hamiltonian_step(start, p0, step_size) and returns: HMCStepData