class_docstr: A sampler for continuous variables based on Hamiltonian mechanics.
  
  See NUTS sampler for automatically tuned stopping time and step size scaling.
class_docstr_tok: ["A","sampler","for","continuous","variables","based","on","Hamiltonian","mechanics",".","See","NUTS","sampler","for","automatically","tuned","stopping","time","and","step","size","scaling","."]
code: def _hamiltonian_step(
      self, start, p0, step_size: float
  ) -> HMCStepData:
      n_steps = max(1, int(self.path_length / step_size))
      n_steps = min(self.max_steps, n_steps)
  
      energy_change = np.inf
      state = start
      last = state
      div_info = None
      try:
          for _ in range(n_steps):
              last = state
              state = self.integrator.step(step_size, state)
      except IntegrationError as e:
          div_info = DivergenceInfo(
              "Integration failed.", e, last, None
          )
      else:
          if not np.isfinite(state.energy):
              div_info = DivergenceInfo(
                  "Divergence encountered, bad energy.",
                  None,
                  last,
                  state,
              )
          energy_change = state.energy - start.energy
          if np.isnan(energy_change):
              energy_change = np.inf
          if np.abs(energy_change) > self.Emax:
              div_info = DivergenceInfo(
                  f"Divergence encountered, energy change larger than {self.Emax}.",
                  None,
                  last,
                  state,
              )
  
      accept_stat = min(1, np.exp(-energy_change))
  
      if div_info is not None or np.random.rand() >= accept_stat:
          end = start
          accepted = False
      else:
          end = state
          accepted = True
  
      stats: dict[str, Any] = {
          "path_length": self.path_length,
          "n_steps": n_steps,
          "accept": accept_stat,
          "energy_error": energy_change,
          "energy": state.energy,
          "accepted": accepted,
          "model_logp": state.model_logp,
      }
      # Retrieve State q and p data from respective RaveledVars
      end = State(
          end.q.data,
          end.p.data,
          end.v,
          end.q_grad,
          end.energy,
          end.model_logp,
          end.index_in_trajectory,
      )
      stats.update(self.potential.stats())
      return HMCStepData(end, accept_stat, div_info, stats)
  
file_path: pymc/pymc/step_methods/hmc/hmc.py
imports: from __future__ import annotations
  from typing import Any
  import numpy
  from pymc.stats.convergence import SamplerWarning
  from pymc.step_methods.compound import Competence
  from pymc.step_methods.hmc.base_hmc import BaseHMC, DivergenceInfo, HMCStepData
  from pymc.step_methods.hmc.integration import IntegrationError, State
  from pymc.vartypes import discrete_types
label_desc: Use image node_id 2 for calling the HamiltonianMC obj's underlying member method code with example usage: obj._hamiltonian_step(start, p0, step_size) and returns: HMCStepData