Source code for openff.interchange.drivers.all

"""Functions for running energy evluations with all available engines."""

import warnings
from collections.abc import Iterable

from openff.utilities.utilities import requires_package
from pandas import DataFrame

from openff.interchange import Interchange
from openff.interchange.drivers.amber import get_amber_energies
from openff.interchange.drivers.gromacs import get_gromacs_energies
from openff.interchange.drivers.lammps import get_lammps_energies
from openff.interchange.drivers.openmm import get_openmm_energies
from openff.interchange.drivers.report import EnergyReport
from openff.interchange.exceptions import (
    AmberError,
    GMXError,
    LAMMPSError,
    UnsupportedCutoffMethodError,
)


[docs]def get_all_energies( interchange: "Interchange", combine_nonbonded_forces: bool = False, _engines: Iterable[str] = ("OpenMM", "Amber", "GROMACS", "LAMMPS"), ) -> dict[str, EnergyReport]: """ Given an Interchange object, return single-point energies as computed by all available engines. """ # TODO: Return something nan-like if one driver fails, but still return others that succeed # TODO: Have each driver return the version of the engine that was used all_energies: dict[str, EnergyReport] = dict() try: # TODO: Worth wiring this argument up to this function? kwargs complexity is not fun all_energies["OpenMM"] = get_openmm_energies( interchange, combine_nonbonded_forces=combine_nonbonded_forces, ) except UnsupportedCutoffMethodError as error: warnings.warn( f"Skipping OpenMM, driver failed with error:\n\t{error}", stacklevel=2, ) for engine_name, engine_driver, engine_exception in [ ("Amber", get_amber_energies, AmberError), ("GROMACS", get_gromacs_energies, GMXError), ("LAMMPS", get_lammps_energies, LAMMPSError), ]: if engine_name not in _engines: continue try: all_energies[engine_name] = engine_driver(interchange=interchange) # type: ignore[operator] except engine_exception: pass return all_energies
[docs]@requires_package("pandas") def get_summary_data( interchange: "Interchange", combine_nonbonded_forces: bool = False, _engines: Iterable[str] = ("OpenMM", "Amber", "GROMACS", "LAMMPS"), ) -> "DataFrame": """Return a pandas DataFrame with summaries of energies from all available engines.""" from openff.toolkit import unit from pandas import DataFrame kj_mol = unit.kilojoule / unit.mol energies = get_all_energies( interchange, combine_nonbonded_forces=combine_nonbonded_forces, _engines=_engines, ) for k, v in energies.items(): for kk in v.energies: energies[k].energies[kk] = energies[k].energies[kk].m_as(kj_mol) # type: ignore[union-attr] return DataFrame({k: v.energies for k, v in energies.items()}).T