Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate Python config files #1104

Merged
merged 18 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .codecov.yml

This file was deleted.

7 changes: 2 additions & 5 deletions .github/workflows/beta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ jobs:

env:
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
COV: --cov=openff/interchange --cov-report=xml --cov-config=setup.cfg --cov-append

steps:
- uses: actions/checkout@v4
Expand All @@ -52,9 +51,7 @@ jobs:
python=${{ matrix.python-version }}

- name: Install package
run: |
micromamba remove --force openff-interchange openff-interchange-base
python -m pip install . plugins/
run: python -m pip install . plugins/

- name: Install and license OpenEye Toolkits
if: ${{ matrix.openeye == true }}
Expand All @@ -71,7 +68,7 @@ jobs:

- name: Run all tests
if: always()
run: python -m pytest -v $COV openff/interchange/
run: python -m pytest -v openff/interchange/

- name: Codecov
uses: codecov/codecov-action@v5
Expand Down
13 changes: 2 additions & 11 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ jobs:
name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }}, OpenMM ${{ matrix.openmm }}, OpenEye ${{ matrix.openeye }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- macos-latest
Expand All @@ -33,11 +32,10 @@ jobs:
- false
openmm:
- true
- false

env:
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
COV: --cov=openff/interchange --cov-report=xml --cov-config=setup.cfg --cov-append
COV: --cov=openff/interchange --cov-report=xml --cov-config=pyproject.toml --cov-append

steps:
- uses: actions/checkout@v4
Expand All @@ -52,11 +50,7 @@ jobs:
python=${{ matrix.python-version }}

- name: Install package
run: |
# These packages are brought in by conda (via the toolkit) and must be removed manually
# since pip doesn't know about the -base split and does not uninstall the -base package
micromamba remove --force openff-interchange openff-interchange-base
python -m pip install . plugins/
run: python -m pip install . plugins/

- name: Install and license OpenEye Toolkits
if: ${{ matrix.openeye == true }}
Expand Down Expand Up @@ -85,9 +79,6 @@ jobs:
# and also uninstalls RDKit
run: micromamba install rdkit "ambertools =23" "lammps >=2023.08.02" "jax >=0.3" "jaxlib >=0.3" -c conda-forge

- name: Install Foyer
run: micromamba install "foyer >=0.12.1" -c conda-forge -yq

- name: Run tests
run: python -m pytest $COV openff/interchange/ -r fExs -n logical --durations=10

Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ defaults:

jobs:
test:
name: Examples on ${{ matrix.os }}, Python ${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
Expand All @@ -45,8 +45,7 @@ jobs:
python=${{ matrix.python-version }}

- name: Install package
run: |
python -m pip install .
run: python -m pip install .

- name: License OpenEye
run: |
Expand All @@ -56,12 +55,10 @@ jobs:
SECRET_OE_LICENSE: ${{ secrets.OE_LICENSE }}

- name: Run docexamples
run: |
python -m pytest --doctest-modules openff/interchange/ --ignore=openff/interchange/_tests
run: python -m pytest -c /dev/null/ --doctest-modules openff/interchange/ --ignore=openff/interchange/_tests

- name: Run example notebooks
if: always()
run: |
python -m pytest --nbval-lax --dist loadscope -n logical --durations=20 examples/ \
python -m pytest -c /dev/null/ --nbval-lax --dist loadscope -n logical --durations=20 examples/ \
--ignore=examples/deprecated/ \
--ignore=examples/experimental
5 changes: 2 additions & 3 deletions devtools/conda-envs/examples_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ dependencies:
# Optional features
- openff-nagl ~=0.5
- openff-nagl-models ~=0.3
- mbuild ~=0.18
- foyer =1
- gmso ~=0.12
- mbuild
- foyer
- nglview
# Drivers
- gromacs
Expand Down
1 change: 0 additions & 1 deletion devtools/conda-envs/test_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies:
- openff-nagl-models ~=0.3
- mbuild =1
- foyer =1
- gmso ~=0.12
- nglview
# Drivers
- gromacs
Expand Down
2 changes: 1 addition & 1 deletion docs/developing.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Style is enforced with automated linters that run in CI. See `.github/workflows/

### Type-checking

Type hints are **optional** but encouraged. Many optional flags are passed to `mypy`; check the action for a recommended invocation. Check `setup.cfg` for some configuration, mostly ignoring libraries that do not have support for type-checking.
Type hints are **optional** but encouraged. Many optional flags are passed to `mypy`; check the action for a recommended invocation. Check `pyproject.toml` for some configuration, mostly ignoring libraries that do not have support for type-checking.

### Pre-commit

Expand Down
5 changes: 3 additions & 2 deletions openff/interchange/_tests/energy_tests/test_energies.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
)
from openff.interchange.constants import kj_mol
from openff.interchange.drivers import get_openmm_energies
from openff.interchange.foyer._guard import has_foyer

if has_package("openmm"):
import openmm
Expand All @@ -31,7 +32,7 @@
from openff.interchange.drivers.lammps import get_lammps_energies


@skip_if_missing("foyer")
@pytest.mark.skipif(not has_foyer, reason="Foyer is not installed")
class TestEnergies:
@pytest.fixture(scope="session")
def oplsaa(self):
Expand Down Expand Up @@ -99,7 +100,7 @@ def test_energies_single_mol(self, constrained, sage, sage_unconstrained, mol_sm
lmp_energies.compare(other_energies, tolerances)

@needs_gmx
@skip_if_missing("foyer")
@pytest.mark.skipif(not has_foyer, reason="Foyer is not installed")
@skip_if_missing("mbuild")
def test_process_rb_torsions(self, oplsaa):
"""Test that the GROMACS driver reports Ryckaert-Bellemans torsions"""
Expand Down
15 changes: 7 additions & 8 deletions openff/interchange/_tests/unit_tests/components/test_foyer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
import parmed as pmd
import pytest
from openff.toolkit import Molecule, Topology, unit
from openff.utilities.testing import has_package, skip_if_missing
from openff.utilities.testing import skip_if_missing

from openff.interchange import Interchange
from openff.interchange._tests import HAS_GROMACS, get_test_files_dir_path, needs_gmx
from openff.interchange.components.potentials import Potential
from openff.interchange.constants import kj_mol
from openff.interchange.drivers import get_openmm_energies
from openff.interchange.foyer._guard import has_foyer
from openff.interchange.models import PotentialKey, TopologyKey

if has_package("foyer"):
if has_foyer:
import foyer

from openff.interchange.foyer._valence import _RBTorsionHandler
Expand All @@ -27,13 +28,13 @@
)


@skip_if_missing("foyer")
@pytest.mark.skipif(not has_foyer, reason="Foyer is not installed")
class TestFoyer:
@pytest.fixture(scope="session")
@pytest.fixture
def oplsaa(self):
return foyer.forcefields.load_OPLSAA()

@pytest.fixture(scope="session")
@pytest.fixture
def oplsaa_interchange_ethanol(self, oplsaa):
molecule = Molecule.from_file(
get_test_files_dir_path("foyer_test_molecules") / "ethanol.sdf",
Expand All @@ -47,7 +48,7 @@ def oplsaa_interchange_ethanol(self, oplsaa):
interchange.box = [4, 4, 4]
return interchange

@pytest.fixture(scope="session")
@pytest.fixture
def get_interchanges(self, oplsaa):
def interchanges_from_path(molecule_path):
molecule_or_molecules = Molecule.from_file(molecule_path)
Expand Down Expand Up @@ -150,7 +151,6 @@ def test_interchange_energies(self, molecule_path, get_interchanges, oplsaa):
)


@skip_if_missing("foyer")
class TestRBTorsions(TestFoyer):
@pytest.fixture
def ethanol_with_rb_torsions(self, sage):
Expand Down Expand Up @@ -204,7 +204,6 @@ def test_rb_torsions(self, ethanol_with_rb_torsions):
assert (gmx - omm).m_as(kj_mol) < 1e-6

@pytest.mark.filterwarnings("ignore:Parameters have not been assigned to all impropers.")
@skip_if_missing("foyer")
@skip_if_missing("mbuild")
@needs_gmx
def test_rb_torsions_vs_foyer(self, oplsaa, ethanol_with_rb_torsions):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ def test_input_topology_not_modified(self, sage):
@needs_gmx
@needs_lmp
@pytest.mark.slow
@skip_if_missing("foyer")
def test_atom_ordering(self):
"""Test that atom indices in bonds are ordered consistently between the slot map and topology"""
import foyer
Expand Down
15 changes: 8 additions & 7 deletions openff/interchange/_tests/unit_tests/interop/openmm/test_hmr.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import random

import pytest
from openff.toolkit import Molecule, Topology, unit
from openff.toolkit import Molecule, Quantity, Topology

from openff.interchange._tests import MoleculeWithConformer
from openff.interchange.exceptions import NegativeMassError
Expand All @@ -23,7 +23,7 @@ def test_hmr_basic(sage, reversed, ethanol, reversed_ethanol):

system = interchange.to_openmm(hydrogen_mass=hydrogen_mass)

expected_mass = sum([atom.mass for atom in topology.atoms]).m_as(unit.dalton)
expected_mass = sum([atom.mass for atom in topology.atoms]).m_as("dalton")

found_mass = sum(
[
Expand Down Expand Up @@ -53,9 +53,7 @@ def test_hmr_not_applied_to_water(sage, water):

system = interchange.to_openmm(hydrogen_mass=hydrogen_mass)

expected_mass = sum([atom.mass for atom in interchange.topology.atoms]).m_as(
unit.dalton,
)
expected_mass = sum([atom.mass for atom in interchange.topology.atoms]).m_as("dalton")

found_mass = sum(
[
Expand Down Expand Up @@ -109,10 +107,13 @@ def test_hmr_with_ligand_virtual_sites(sage_with_bond_charge, hydrogen_mass):
import openmm
import openmm.unit

molecule = MoleculeWithConformer.from_mapped_smiles("[H:5][C:2]([H:6])([C:3]([H:7])([H:8])[Cl:4])[Cl:1]")
topology = MoleculeWithConformer.from_mapped_smiles(
"[H:5][C:2]([H:6])([C:3]([H:7])([H:8])[Cl:4])[Cl:1]",
).to_topology()
topology.box_vectors = Quantity([4, 4, 4], "nanometer")

# should work fine with 4 fs, but be conservative and just use 3 fs
simulation = sage_with_bond_charge.create_interchange(molecule.to_topology()).to_openmm_simulation(
simulation = sage_with_bond_charge.create_interchange(topology).to_openmm_simulation(
integrator=openmm.VerletIntegrator(3.0 * openmm.unit.femtosecond),
hydrogen_mass=hydrogen_mass,
)
Expand Down
18 changes: 12 additions & 6 deletions openff/interchange/components/interchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,14 @@
import openmm.app
from openff.toolkit import ForceField

if has_package("foyer"):
from foyer import Forcefield as FoyerForcefield
from openff.interchange.foyer._guard import has_foyer

if has_foyer:
try:
from foyer import Forcefield as FoyerForcefield
except ModuleNotFoundError:
# case of openff/interchange/foyer/ being detected as the real package
pass
if has_package("nglview"):
import nglview

Expand Down Expand Up @@ -836,13 +842,13 @@ def from_foyer(

>>> from openff.interchange import Interchange
>>> from openff.toolkit import Molecule, Topology
>>> from foyer import Forcefield
>>> from foyer import Forcefield # doctest: +SKIP
>>> mol = Molecule.from_smiles("CC")
>>> mol.generate_conformers(n_conformers=1)
>>> top = Topology.from_molecules([mol])
>>> oplsaa = Forcefield(name="oplsaa")
>>> interchange = Interchange.from_foyer(topology=top, force_field=oplsaa)
>>> interchange
>>> oplsaa = Forcefield(name="oplsaa") # doctest: +SKIP
>>> interchange = Interchange.from_foyer(topology=top, force_field=oplsaa) # doctest: +SKIP
>>> interchange # doctest: +SKIP
Interchange with 8 collections, non-periodic topology with 8 atoms.

"""
Expand Down
7 changes: 6 additions & 1 deletion openff/interchange/foyer/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
from openff.toolkit import Topology

from openff.interchange.components.potentials import Collection, Potential
from openff.interchange.foyer._guard import has_foyer
from openff.interchange.models import PotentialKey, TopologyKey

if TYPE_CHECKING:
from foyer import Forcefield
if has_foyer:
try:
from foyer import Forcefield
except ModuleNotFoundError:
pass


# Is this the safest way to achieve PotentialKey id separation?
Expand Down
9 changes: 6 additions & 3 deletions openff/interchange/foyer/_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
from numpy.typing import NDArray
from openff.toolkit import Topology
from openff.units import Quantity, unit
from openff.utilities.utilities import has_package

from openff.interchange import Interchange
from openff.interchange.common._positions import _infer_positions
from openff.interchange.components.potentials import Collection
from openff.interchange.foyer._guard import has_foyer
from openff.interchange.foyer._nonbonded import (
FoyerElectrostaticsHandler,
FoyerVDWHandler,
Expand All @@ -21,8 +21,11 @@
)
from openff.interchange.models import TopologyKey

if has_package("foyer"):
from foyer.forcefield import Forcefield
if has_foyer:
try:
from foyer import Forcefield
except ModuleNotFoundError:
pass

_CollectionAlias = type[Collection]

Expand Down
10 changes: 10 additions & 0 deletions openff/interchange/foyer/_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Import guard."""

# openff/interchange/foyer.py causes "import foyer" to not crash, which breaks has_packge("foyer")
# and breaks @skip_if_missing("foyer"), so need a more specific way of checking Foyer installation
try:
from foyer import Forcefield

has_foyer = True
except (ImportError, AttributeError):
has_foyer = False
Loading
Loading