# Path: openpathsampling/integration_tools.py
# def error_if_no(name, package_name, has_package):
# def _chain_import(*packages):
# def error_if_no_simtk_unit(name):
# def error_if_no_mdtraj(name):
# def error_if_to_openmm(name):
#     HAS_SIMTK_UNIT = False
#     HAS_SIMTK_UNIT = True
#     HAS_MDTRAJ = False
#     HAS_MDTRAJ = True
#     HAS_OPENMM = False
#     HAS_OPENMM = True
# 
# Path: openpathsampling/integration_tools.py
# def error_if_no(name, package_name, has_package):
# def _chain_import(*packages):
# def error_if_no_simtk_unit(name):
# def error_if_no_mdtraj(name):
# def error_if_to_openmm(name):
#     HAS_SIMTK_UNIT = False
#     HAS_SIMTK_UNIT = True
#     HAS_MDTRAJ = False
#     HAS_MDTRAJ = True
#     HAS_OPENMM = False
#     HAS_OPENMM = True


from openpathsampling.integration_tools import openmm as mm
from openpathsampling.integration_tools import unit as u
    Returns
    -------
    n_degrees_of_freedom: int
        number of degrees of freedom in this system (after accounting for
        constraints)
    """
    return snapshot.engine.n_degrees_of_freedom()

@property
def instantaneous_temperature(snapshot):
    """
    Returns
    -------
    instantaneous_temperature : openmm.unit.Quantity (temperature)
        instantaneous temperature from the kinetic energy of this snapshot
    """
    # TODO: this can be generalized as a feature that works with any
    # snapshot that has features for KE (in units of kB) and n_dofs

    # if no engine, error here; don't get caught in try/except below
    engine = snapshot.engine
    try:
        old_snap = engine.current_snapshot
    except Exception:  # openmm doesn't use a custom exception class yet
        # Exception: Particle positions have not been set
        old_snap = None
    engine.current_snapshot = snapshot
    state = engine.simulation.context.getState(getEnergy=True)
    # divide by Avogadro b/c OpenMM reports energy/mole
    ke_in_energy = state.getKineticEnergy() / u.AVOGADRO_CONSTANT_NA

# Path: openpathsampling/integration_tools.py
# def error_if_no(name, package_name, has_package):
# def _chain_import(*packages):
# def error_if_no_simtk_unit(name):
# def error_if_no_mdtraj(name):
# def error_if_to_openmm(name):
#     HAS_SIMTK_UNIT = False
#     HAS_SIMTK_UNIT = True
#     HAS_MDTRAJ = False
#     HAS_MDTRAJ = True
#     HAS_OPENMM = False
#     HAS_OPENMM = True
# 
# Path: openpathsampling/integration_tools.py
# def error_if_no(name, package_name, has_package):
# def _chain_import(*packages):
# def error_if_no_simtk_unit(name):
# def error_if_no_mdtraj(name):
# def error_if_to_openmm(name):
#     HAS_SIMTK_UNIT = False
#     HAS_SIMTK_UNIT = True
#     HAS_MDTRAJ = False
#     HAS_MDTRAJ = True
#     HAS_OPENMM = False
#     HAS_OPENMM = True


# Path: openpathsampling/engines/openmm/features/instantaneous_temperature.py
from openpathsampling.integration_tools import openmm as mm
from openpathsampling.integration_tools import unit as u

    Returns
    -------
    n_degrees_of_freedom: int
        number of degrees of freedom in this system (after accounting for
        constraints)
    """
    return snapshot.engine.n_degrees_of_freedom()

@property
def instantaneous_temperature(snapshot):
    """
    Returns
    -------
    instantaneous_temperature : openmm.unit.Quantity (temperature)
        instantaneous temperature from the kinetic energy of this snapshot
    """
    # TODO: this can be generalized as a feature that works with any
    # snapshot that has features for KE (in units of kB) and n_dofs

    # if no engine, error here; don't get caught in try/except below
    engine = snapshot.engine
    try:
        old_snap = engine.current_snapshot
    except Exception:  # openmm doesn't use a custom exception class yet
        # Exception: Particle positions have not been set
        old_snap = None
    engine.current_snapshot = snapshot
    state = engine.simulation.context.getState(getEnergy=True)
    # divide by Avogadro b/c OpenMM reports energy/mole
    ke_in_energy = state.getKineticEnergy() / u.AVOGADRO_CONSTANT_NA

    ke_per_kB = ke_in_energy / u.BOLTZMANN_CONSTANT_kB