diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml deleted file mode 100644 index 98db567a4..000000000 --- a/.github/workflows/CI.yml +++ /dev/null @@ -1,175 +0,0 @@ -name: CI - -on: - push: - branches: - - "main" - pull_request: - branches: - - "main" - schedule: - - cron: "21 0 * * *" - workflow_dispatch: - -defaults: - run: - shell: bash -l {0} - -jobs: - test: - if: (github.event_name == 'schedule' && github.repository == 'openforcefield/openff-toolkit') || (github.event_name != 'schedule') - name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }}, RDKit=${{ matrix.rdkit }}, OpenEye=${{ matrix.openeye }}, NAGL=${{ matrix.nagl }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - python-version: ["3.12", "3.13"] - rdkit: [true, false] - openeye: [true, false] - nagl: [true, false] - exclude: - - rdkit: false - openeye: false - - openeye: true - python-version: "3.13" - - rdkit: false - nagl: true - - env: - OE_LICENSE: ${{ github.workspace }}/oe_license.txt - PYTEST_ARGS: -r fE --tb=short -nauto - COV: --cov=openff/toolkit/ --cov-append --cov-report=xml - - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Set environment variables - run: | - if [[ ${{ matrix.openeye }} == true && ${{ matrix.rdkit }} == true ]]; then - echo "ENVFILE=test_env" >> $GITHUB_ENV - echo "JOBNAME=RDKit and OpenEye" >> $GITHUB_ENV - echo "TOOLKIT_CHECKS=RDKIT OPENEYE" >> $GITHUB_ENV - echo "PACKAGES_TO_REMOVE=" >> $GITHUB_ENV - fi - - if [[ ${{ matrix.openeye }} == true && ${{ matrix.rdkit }} == false ]]; then - echo "ENVFILE=openeye" >> $GITHUB_ENV - echo "JOBNAME=OpenEye" >> $GITHUB_ENV - echo "TOOLKIT_CHECKS=OPENEYE" >> $GITHUB_ENV - echo "PACKAGES_TO_REMOVE=ambertools rdkit" >> $GITHUB_ENV - fi - - if [[ ${{ matrix.openeye }} == false && ${{ matrix.rdkit }} == true ]]; then - echo "ENVFILE=rdkit" >> $GITHUB_ENV - echo "JOBNAME=RDKit" >> $GITHUB_ENV - echo "TOOLKIT_CHECKS=RDKIT" >> $GITHUB_ENV - echo "PACKAGES_TO_REMOVE=openeye-toolkits" >> $GITHUB_ENV - fi - - - name: Install environment with ${{ env.JOBNAME }} - uses: mamba-org/setup-micromamba@v3 - with: - environment-file: devtools/conda-envs/${{ env.ENVFILE }}.yaml - create-args: >- - python=${{ matrix.python-version }} - - - name: Make oe_license.txt file from GH org secret "OE_LICENSE" - env: - OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }} - run: echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE} - - - name: Install package - run: | - # While Interchange is being installed with pip, there is no need to - # force uninstall openff-toolkit-base since it's only pulled in when - # Interchange is installed with conda. Un-comment this when testing - # against a conda build of Interchange. (It may also be pulled down - # by `openmmforcefields` and should be removed in that case a well.) - micromamba remove --force openff-toolkit openff-toolkit-base - python -m pip install . - - - name: Install test plugins - run: python -m pip install utilities/test_plugins - - - name: Remove undesired toolkits - run: | - if [ ! -z "${{ env.PACKAGES_TO_REMOVE }}" ]; then - for cpkg in ${{ env.PACKAGES_TO_REMOVE }}; do - if [[ $(micromamba list | grep $cpkg) ]]; then micromamba remove --force $cpkg --yes ; fi - done - fi - - - name: Optionally remove OpenFF NAGL - if: ${{ matrix.nagl == false }} - run: micromamba remove openff-nagl-base openff-nagl-models - - - name: Check installed toolkits - run: | - for tk in ${{ env.TOOLKIT_CHECKS }}; do - python -c "from openff.toolkit.utils.toolkits import ${tk}_AVAILABLE; assert ${tk}_AVAILABLE, '${tk} unavailable'" - done - - - name: Check uninstalled toolkits - run: | - if [ ! -z "${{ env.PACKAGES_TO_REMOVE }}" ]; then - for tk in ${{ env.PACKAGES_TO_REMOVE }}; do - TK=$(echo ${tk%-*} | tr 'a-z' 'A-Z') - python -c "from openff.toolkit.utils.toolkits import ${TK}_AVAILABLE; assert not ${TK}_AVAILABLE, '${TK} available'" - done - fi - - - name: Environment Information - run: | - micromamba info - micromamba list - pip list - - - name: Run mypy - # When possible re-enable this with OE+RDK=True, but for now rdkit builds often have bugs - # in stubs and there are other subtleties (in the source code and builds) that reduce the number - # of available builds. - # See ex https://github.com/rdkit/rdkit/issues/7221 - # and https://github.com/rdkit/rdkit/issues/7583 - if: ${{ matrix.rdkit == false && matrix.openeye == true }} - run: mypy -p "openff.toolkit" - - - name: Run unit tests - run: | - PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_examples.py" - PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_links.py" - - # TODO: Flip back to schedule condition before merge - PYTEST_ARGS+=" --runslow" - - python -m pytest -x --durations=20 $PYTEST_ARGS $COV openff/toolkit/_tests - - - name: Run code snippets in docs - if: ${{ matrix.rdkit == true && matrix.openeye == true && matrix.nagl == true }} - run: pytest -v --no-cov --doctest-glob="docs/*.rst" --doctest-glob="docs/*.md" docs/ - - - name: Run notebooks in docs - if: ${{ matrix.rdkit == true && matrix.openeye == true }} - run: python -m pytest -v --durations=10 --no-cov --nbval-lax docs/ - - - name: Run examples in docstrings - if: ${{ matrix.rdkit == true && matrix.openeye == true && matrix.nagl == true }} - run: | - pytest openff \ - -v -x -n logical --no-cov --doctest-modules \ - --ignore-glob='openff/toolkit/_tests*' \ - --ignore=openff/toolkit/data/ \ - --ignore=openff/toolkit/utils/utils.py - - - name: Codecov - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./coverage.xml - disable_search: true - fail_ci_if_error: true - - - name: Check links - if: ${{ matrix.rdkit == true && matrix.openeye == true }} - run: pytest -r fE --tb=short openff/toolkit/_tests/test_links.py diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0943458e7..d08dde6df 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -25,16 +25,9 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] python-version: [ "3.12"] - rdkit: [true, false] + rdkit: [true] openeye: [true, false] - nagl: [true, false] - exclude: - - rdkit: false - openeye: false - - rdkit: true - openeye: true - - rdkit: false - nagl: true + nagl: [true] env: OE_LICENSE: ${{ github.workspace }}/oe_license.txt @@ -47,64 +40,35 @@ jobs: with: fetch-depth: 0 - - name: Set environment variables - run: | - if [[ ${{ matrix.openeye }} == true && ${{ matrix.rdkit }} == false ]]; then - echo "ENVFILE=openeye" >> $GITHUB_ENV - echo "TOOLKIT_CHECKS=OPENEYE" >> $GITHUB_ENV - echo "PACKAGES_TO_REMOVE=ambertools rdkit" >> $GITHUB_ENV - fi - - if [[ ${{ matrix.openeye }} == false && ${{ matrix.rdkit }} == true ]]; then - echo "ENVFILE=rdkit" >> $GITHUB_ENV - echo "TOOLKIT_CHECKS=RDKIT" >> $GITHUB_ENV - echo "PACKAGES_TO_REMOVE=openeye-toolkits" >> $GITHUB_ENV - fi - - - name: Install conda environment with ${{ env.ENVFILE }} + - name: Install base conda environment uses: mamba-org/setup-micromamba@v3 with: - environment-file: devtools/conda-envs/${{env.ENVFILE}}-examples.yaml + environment-file: devtools/conda-envs/base-examples.yaml create-args: >- python=${{ matrix.python-version }} + - name: Install OpenEye toolkits + if: ${{ matrix.openeye == true }} + run: micromamba install -c openeye "openeye-toolkits >=2024" -y + - name: Make oe_license.txt file from GH org secret "OE_LICENSE" + if: ${{ matrix.openeye == true }} env: OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }} run: echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE} - - name: Optionally remove OpenFF NAGL - if: ${{ matrix.nagl == false }} - run: micromamba remove openff-nagl-base openff-nagl-models --force - - name: Install package run: python -m pip install . - - name: Remove undesired toolkits + - name: Check OpenEye installed + if: ${{ matrix.openeye == true }} run: | - # If openmmforcefields is included in either environment file, - # remove RDKit and AmberTools brought in by it. Currently it's not included, - # so don't remove it. - if [ ! -z "${{ env.PACKAGES_TO_REMOVE }}" ]; then - for cpkg in ${{ env.PACKAGES_TO_REMOVE }}; do - if [[ $(micromamba list | grep $cpkg) ]]; then micromamba remove --force $cpkg --yes ; fi - done - fi - - - name: Check installed toolkits - run: | - for tk in ${{ env.TOOLKIT_CHECKS }}; do - python -c "from openff.toolkit.utils.toolkits import ${tk}_AVAILABLE; assert ${tk}_AVAILABLE, '${tk} unavailable'" - done + python -c "from openff.toolkit.utils.toolkits import OPENEYE_AVAILABLE; assert OPENEYE_AVAILABLE, 'OpenEye unavailable'" - - name: Check uninstalled toolkits + - name: Check OpenEye NOT installed + if: ${{ matrix.openeye == false }} run: | - if [ ! -z "${{ env.PACKAGES_TO_REMOVE }}" ]; then - for tk in ${{ env.PACKAGES_TO_REMOVE }}; do - TK=$(echo ${tk%-*} | tr 'a-z' 'A-Z') - python -c "from openff.toolkit.utils.toolkits import ${TK}_AVAILABLE; assert not ${TK}_AVAILABLE, '${TK} available'" - done - fi + python -c "from openff.toolkit.utils.toolkits import OPENEYE_AVAILABLE; assert not OPENEYE_AVAILABLE, 'OpenEye available but shouldn\'t be'" - name: Environment Information run: | @@ -114,25 +78,10 @@ jobs: - name: Run example scripts run: | - if [[ ${{ matrix.rdkit }} == false ]]; then - PYTEST_ARGS+=" --ignore=examples/check_dataset_parameter_coverage" - PYTEST_ARGS+=" --ignore=examples/QCArchive_interface" - fi pytest $PYTEST_ARGS openff/toolkit/_tests/test_examples.py - name: Run example notebooks run: | - if [[ ${{ matrix.rdkit }} == false ]]; then - NB_ARGS+=" --ignore=examples/QCArchive_interface" - NB_ARGS+=" --ignore=examples/visualization" - NB_ARGS+=" --ignore=examples/check_dataset_parameter_coverage" - NB_ARGS+=" --ignore=examples/conformer_energies" - NB_ARGS+=" --ignore=examples/using_smirnoff_in_amber_or_gromacs" - NB_ARGS+=" --ignore=examples/using_smirnoff_with_amber_protein_forcefield" - NB_ARGS+=" --ignore=examples/SMIRNOFF_simulation" - NB_ARGS+=" --ignore=examples/toolkit_showcase" - fi - # GROMACS builds are not stable on macOS + GHA if [[ ${{ matrix.os }} == macos-latest ]]; then NB_ARGS+=" --ignore=examples/using_smirnoff_in_amber_or_gromacs/" diff --git a/devtools/conda-envs/rdkit-examples.yaml b/devtools/conda-envs/base-examples.yaml similarity index 90% rename from devtools/conda-envs/rdkit-examples.yaml rename to devtools/conda-envs/base-examples.yaml index dbb60133e..ff04213f9 100644 --- a/devtools/conda-envs/rdkit-examples.yaml +++ b/devtools/conda-envs/base-examples.yaml @@ -1,4 +1,4 @@ -name: rdkit-examples +name: base-examples channels: - conda-forge dependencies: @@ -24,10 +24,8 @@ dependencies: - openff-nagl-models >=0.3.0 - typing_extensions - nglview - # Toolkit-specific - - ambertools # https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583 - - rdkit =2024 + - rdkit >=2024 # Test-only/optional/dev/typing/examples - pytest =8 - pytest-xdist @@ -42,5 +40,5 @@ dependencies: - nbval - mdtraj - pdbfixer - - openmmforcefields >=0.11.2 + # openmmforcefields >=0.15 - gromacs >=2023.3 diff --git a/devtools/conda-envs/openeye-examples.yaml b/devtools/conda-envs/openeye-examples.yaml deleted file mode 100644 index d43f0f69e..000000000 --- a/devtools/conda-envs/openeye-examples.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: openeye-examples -channels: - - openeye - - conda-forge -dependencies: - # Base depends - - python - - versioningit - - packaging - - numpy <2.3 - - networkx - - cachetools - # https://github.com/openforcefield/openff-toolkit/issues/2150 - - xmltodict <=1.0.2 - - python-constraint - - openmm >=7.6 - - openff-forcefields >=2023.11 - - openff-amber-ff-ports >=0.0.3 - - openff-units - - openff-utilities >=0.1.5 - - openff-interchange-base >=0.5 - # No idea why this is necessary, see https://github.com/openforcefield/openff-toolkit/pull/1821 - - nomkl - - openff-nagl-base >=0.4.0 - - openff-nagl-models >=0.3.0 - - typing_extensions - - nglview - # Toolkit-specific - - openeye-toolkits - # Test-only/optional/dev/typing/examples - - pytest =8 - - pytest-xdist - - pytest-rerunfailures - - pyyaml - - toml - - bson - - msgpack-python - - qcelemental - - qcportal >=0.50 - - qcengine - - mdtraj - - nbval - - pdbfixer - - openmmforcefields >=0.11.2 - - gromacs >=2023.3 diff --git a/devtools/conda-envs/rdkit.yaml b/devtools/conda-envs/rdkit.yaml index 6f1d980ce..93bcb6e3a 100644 --- a/devtools/conda-envs/rdkit.yaml +++ b/devtools/conda-envs/rdkit.yaml @@ -21,8 +21,6 @@ dependencies: - openff-nagl-base >=0.4.0 - openff-nagl-models >=0.3.0 - typing_extensions - # Toolkit-specific - - ambertools >=22 # https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583 - rdkit !=2024.03.6,!=2024.03.5 # Test-only/optional/dev/typing diff --git a/examples/SMIRNOFF_simulation/run_simulation.ipynb b/examples/SMIRNOFF_simulation/run_simulation.ipynb index 020688f3d..1d21748fd 100644 --- a/examples/SMIRNOFF_simulation/run_simulation.ipynb +++ b/examples/SMIRNOFF_simulation/run_simulation.ipynb @@ -114,7 +114,7 @@ ")\n", "\n", "# Load the OpenFF \"Sage\" force field.\n", - "forcefield = ForceField(\"openff-2.2.0.offxml\")\n", + "forcefield = ForceField(\"openff-2.3.0.offxml\")\n", "\n", "# Parametrize the topology and create an Interchange object.\n", "interchange = forcefield.create_interchange(topology)" diff --git a/examples/conformer_energies/conformer_energies.py b/examples/conformer_energies/conformer_energies.py index f1ce7c8ee..80e5b460e 100644 --- a/examples/conformer_energies/conformer_energies.py +++ b/examples/conformer_energies/conformer_energies.py @@ -41,8 +41,8 @@ def compute_conformer_energies_from_file(filename): + f" ({molecule.name})" ) - # Load the openff-2.2.1 force field appropriate for vacuum calculations (without constraints) - forcefield = ForceField("openff_unconstrained-2.2.1.offxml") + # Load the openff-2.3.0 force field appropriate for vacuum calculations (without constraints) + forcefield = ForceField("openff_unconstrained-2.3.0.offxml") # Create an Interchange object, which stores the result of parametrizing with this force field print(f"Parametrizing {molecule.name} (may take a moment to calculate charges)...") interchange = forcefield.create_interchange(molecule.to_topology()) diff --git a/examples/deprecated/check_dataset_parameter_coverage/check_parameter_coverage.ipynb b/examples/deprecated/check_dataset_parameter_coverage/check_parameter_coverage.ipynb index 6f99c26be..5c10937ae 100644 --- a/examples/deprecated/check_dataset_parameter_coverage/check_parameter_coverage.ipynb +++ b/examples/deprecated/check_dataset_parameter_coverage/check_parameter_coverage.ipynb @@ -651,7 +651,7 @@ "source": [ "start_time = time.time()\n", "\n", - "forcefield = ForceField(\"openff-2.0.0.offxml\")\n", + "forcefield = ForceField(\"openff-2.3.0.offxml\")\n", "\n", "results = {}\n", "\n", diff --git a/examples/deprecated/using_smirnoff_with_amber_protein_forcefield/toluene_in_T4_lysozyme.ipynb b/examples/deprecated/using_smirnoff_with_amber_protein_forcefield/toluene_in_T4_lysozyme.ipynb index 8d58605ef..ed2727104 100644 --- a/examples/deprecated/using_smirnoff_with_amber_protein_forcefield/toluene_in_T4_lysozyme.ipynb +++ b/examples/deprecated/using_smirnoff_with_amber_protein_forcefield/toluene_in_T4_lysozyme.ipynb @@ -76,7 +76,7 @@ " unique_molecules=[Molecule.from_smiles(\"Cc1ccccc1\")],\n", ")\n", "\n", - "sage = ForceField(\"openff-2.0.0.offxml\")\n", + "sage = ForceField(\"openff-2.3.0.offxml\")\n", "\n", "toluene = sage.create_interchange(toluene_topology)" ] diff --git a/examples/forcefield_modification/forcefield_modification.ipynb b/examples/forcefield_modification/forcefield_modification.ipynb index 80b65b830..8e59b8857 100644 --- a/examples/forcefield_modification/forcefield_modification.ipynb +++ b/examples/forcefield_modification/forcefield_modification.ipynb @@ -96,7 +96,7 @@ "ligand_smiles = \"CC(C)(C)c1c(O)c(O)c2c(c1O)[C@H]1OCCC[C@H]1[C@H](c1cc(O)c(O)c(F)c1)N2\"\n", "ligand = Molecule.from_smiles(ligand_smiles)\n", "ligand.generate_conformers(n_conformers=1)\n", - "force_field = ForceField(\"openff-2.2.0.offxml\")" + "force_field = ForceField(\"openff-2.3.0.offxml\")" ] }, { @@ -1862,7 +1862,7 @@ "metadata": {}, "outputs": [], "source": [ - "force_field = ForceField(\"openff-2.1.0.offxml\")\n", + "force_field = ForceField(\"openff-2.3.0.offxml\")\n", "cyclic_nitrogen_angle = force_field[\"Angles\"].parameters[cyclic_nitrogen_smirks]\n", "cyclic_nitrogen_angle.angle = 179 * unit.degree" ] diff --git a/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb b/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb index b947e0ea8..adcb62bfb 100644 --- a/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb +++ b/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb @@ -125,7 +125,7 @@ "topology = Topology.from_molecules([molecule])\n", "\n", "# Let's label using the Sage force field\n", - "forcefield = ForceField(\"openff-2.2.0.offxml\")\n", + "forcefield = ForceField(\"openff-2.3.0.offxml\")\n", "\n", "# Run the molecule labeling\n", "molecule_force_list = forcefield.label_molecules(topology)\n", @@ -475,7 +475,7 @@ "mols = [Molecule.from_smiles(smiles) for smiles in molecule_smiles]\n", "\n", "# Let's label using the original \"Sage\" force field\n", - "forcefield = ForceField(\"openff-2.1.0.offxml\")\n", + "forcefield = ForceField(\"openff-2.0.0.offxml\")\n", "\n", "# This utility function creates dictionaries describing parameter assignment,\n", "# grouped both by molecule and by parameter\n", diff --git a/examples/toolkit_showcase/toolkit_showcase.ipynb b/examples/toolkit_showcase/toolkit_showcase.ipynb index 7eef9b1a8..cfb1c17aa 100644 --- a/examples/toolkit_showcase/toolkit_showcase.ipynb +++ b/examples/toolkit_showcase/toolkit_showcase.ipynb @@ -520,7 +520,7 @@ "metadata": {}, "outputs": [], "source": [ - "sage_ff14sb = ForceField(\"openff-2.2.0.offxml\", \"ff14sb_off_impropers_0.0.4.offxml\")" + "sage_ff14sb = ForceField(\"openff-2.3.0.offxml\", \"ff14sb_off_impropers_0.0.4.offxml\")" ] }, { diff --git a/examples/using_smirnoff_in_amber_or_gromacs/.gitignore b/examples/using_smirnoff_in_amber_or_gromacs/.gitignore deleted file mode 100644 index c6cb27f90..000000000 --- a/examples/using_smirnoff_in_amber_or_gromacs/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -system.* -system_pointenergy.* -log.lammps -out.lmp -tmp.in diff --git a/examples/using_smirnoff_in_amber_or_gromacs/1_cyclohexane_1_ethanol.pdb b/examples/using_smirnoff_in_amber_or_gromacs/1_cyclohexane_1_ethanol.pdb deleted file mode 100644 index 6c44bc5ca..000000000 --- a/examples/using_smirnoff_in_amber_or_gromacs/1_cyclohexane_1_ethanol.pdb +++ /dev/null @@ -1,61 +0,0 @@ -REMARK 1 CREATED WITH MDTraj 1.7.2, 2016-06-27 -CRYST1 31.885 31.885 31.885 90.00 90.00 90.00 P 1 1 -MODEL 0 -ATOM 1 C1 ZBE A 1 12.532 10.813 10.386 1.00 0.00 C -ATOM 2 C2 ZBE A 1 12.348 10.339 11.825 1.00 0.00 C -ATOM 3 C3 ZBE A 1 10.880 10.365 12.244 1.00 0.00 C -ATOM 4 C4 ZBE A 1 10.256 11.739 12.020 1.00 0.00 C -ATOM 5 C5 ZBE A 1 10.439 12.213 10.581 1.00 0.00 C -ATOM 6 C6 ZBE A 1 11.907 12.187 10.162 1.00 0.00 C -ATOM 7 H1 ZBE A 1 12.072 10.088 9.703 1.00 0.00 H -ATOM 8 H2 ZBE A 1 13.600 10.849 10.143 1.00 0.00 H -ATOM 9 H3 ZBE A 1 12.745 9.324 11.932 1.00 0.00 H -ATOM 10 H4 ZBE A 1 12.930 10.982 12.497 1.00 0.00 H -ATOM 11 H5 ZBE A 1 10.324 9.614 11.669 1.00 0.00 H -ATOM 12 H6 ZBE A 1 10.793 10.088 13.300 1.00 0.00 H -ATOM 13 H7 ZBE A 1 9.188 11.703 12.264 1.00 0.00 H -ATOM 14 H8 ZBE A 1 10.716 12.464 12.704 1.00 0.00 H -ATOM 15 H9 ZBE A 1 9.858 11.571 9.909 1.00 0.00 H -ATOM 16 H10 ZBE A 1 10.043 13.230 10.474 1.00 0.00 H -ATOM 17 H11 ZBE A 1 11.994 12.465 9.105 1.00 0.00 H -ATOM 18 H12 ZBE A 1 12.463 12.938 10.737 1.00 0.00 H -TER 19 ZBE A 1 -ATOM 20 C1 ZXQ S 1 10.172 31.276 27.866 1.00 0.00 C -ATOM 21 C2 ZXQ S 1 8.746 30.961 27.471 1.00 0.00 C -ATOM 22 O1 ZXQ S 1 8.752 30.264 26.234 1.00 0.00 O -ATOM 23 H1 ZXQ S 1 10.204 31.815 28.818 1.00 0.00 H -ATOM 24 H2 ZXQ S 1 10.758 30.356 27.962 1.00 0.00 H -ATOM 25 H3 ZXQ S 1 10.661 31.886 27.099 1.00 0.00 H -ATOM 26 H4 ZXQ S 1 8.169 31.883 27.352 1.00 0.00 H -ATOM 27 H5 ZXQ S 1 8.267 30.333 28.228 1.00 0.00 H -ATOM 28 H6 ZXQ S 1 7.826 30.079 26.011 1.00 0.00 H -TER 29 ZXQ S 1 -ENDMDL -CONECT 1 6 2 7 8 -CONECT 2 1 3 9 10 -CONECT 3 2 4 11 12 -CONECT 4 3 5 13 14 -CONECT 5 4 6 15 16 -CONECT 6 1 5 17 18 -CONECT 7 1 -CONECT 8 1 -CONECT 9 2 -CONECT 10 2 -CONECT 11 3 -CONECT 12 3 -CONECT 13 4 -CONECT 14 4 -CONECT 15 5 -CONECT 16 5 -CONECT 17 6 -CONECT 18 6 -CONECT 20 21 23 24 25 -CONECT 21 20 22 26 27 -CONECT 22 21 28 -CONECT 23 20 -CONECT 24 20 -CONECT 25 20 -CONECT 26 21 -CONECT 27 21 -CONECT 28 22 -END diff --git a/examples/using_smirnoff_in_amber_or_gromacs/README.md b/examples/using_smirnoff_in_amber_or_gromacs/README.md deleted file mode 100644 index 0004fae16..000000000 --- a/examples/using_smirnoff_in_amber_or_gromacs/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## Export OpenFF-generated OpenMM System to AMBER and GROMACS files - -This example shows how you can convert an OpenMM `System` generated with the Open Forcefield Toolkit, which can be simulated natively with OpenMM, into AMBER prmtop/inpcrd and GROMACS top/gro input files through the ParmEd library. - -#### Manifest: - -- `export_with_interchange.ipynyb`: IPython notebook showing how to generate AMBER and GROMACS topology and coordinates files starting from a PDB using Interchange. -- `1_cyclohexane_1_ethanol.pdb`: PDB file containing one molecule of cyclohexane and one of ethanol in vacuum. diff --git a/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb b/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb deleted file mode 100644 index ae5ca5995..000000000 --- a/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb +++ /dev/null @@ -1,548 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using OpenFF force fields in Amber and GROMACS\n", - "\n", - "The OpenFF Toolkit can create create parametrized `openmm.System` objects and also, with an extra API call to [Interchange](https://docs.openforcefield.org/projects/interchange/en/stable/), input files for simulations in Amber and GROMACS. This example prepares a system, parametrizes it with Sage, shows how simple it is to write Amber and GROMACS files, and also validates the results." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "### Preparing an OpenFF Topology\n", - "\n", - "We start by loading a PDB file containing one copy of ethanol and cyclohexane. Our goal is to create an OpenFF `Topology` object describing this system that we can parametrize with the SMIRNOFF-format \"Sage\" force field.\n", - "\n", - "The two `Molecule` objects created from the SMILES strings can contain information such as formal charges and stereochemistry that is not included in a PDB file. These objects are passed to the PDB loading function via the `unique_molecules` argument. In this example, partial charges are not explicitly given, and `ForceField` will assign AM1/BCC charges as specified by the \"Sage\" force field. Note that the OpenFF Toolkit produces partial charges that do not depend on the input conformation of parameterized molecules. See the [FAQ](https://open-forcefield-toolkit.readthedocs.io/en/latest/faq.html#the-partial-charges-generated-by-the-toolkit-don-t-seem-to-depend-on-the-molecule-s-conformation-is-this-a-bug) for more information." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from pprint import pprint\n", - "from shutil import which\n", - "\n", - "from openff.toolkit import ForceField, Molecule, Topology" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b07109876e16434196fa290e741373d6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "96b0327def004eac87b3bb79d54527f1", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "NGLWidget()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "ethanol = Molecule.from_smiles(\"CCO\")\n", - "cyclohexane = Molecule.from_smiles(\"C1CCCCC1\")\n", - "\n", - "# Load the topology from a PDB file and `Molecule` objects\n", - "topology = Topology.from_pdb(\n", - " \"1_cyclohexane_1_ethanol.pdb\",\n", - " unique_molecules=[ethanol, cyclohexane],\n", - ")\n", - "\n", - "topology.visualize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preparing an OpenFF ForceField\n", - "\n", - "Once the `ForceField` class is imported, the only decision to make is which force field to use. An exhaustive list of force fields released by the Open Force Field Initiative can be found [here](https://github.com/openforcefield/openff-forcefields#how-to-cite).\n", - "\n", - "Here we will use force field from the \"Sage\" line." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "forcefield = ForceField(\"openff-2.2.0.offxml\")\n", - "forcefield" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preparing an OpenMM System\n", - "\n", - "Once a force field and topology have been loaded, an `openmm.System` can be generated natively with the OpenFF Toolkit." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - " >" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "omm_system = forcefield.create_openmm_system(topology)\n", - "omm_system" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "### Preparing an Interchange object\n", - "\n", - "To export to engines other than OpenMM, we will make use of the [Interchange](https://openff-interchange.readthedocs.io/) project. There is a high-level `ForceField.create_interchange` method which acts much like `ForceField.create_openmm_system`. It uses OpenFF `Topology` and `ForceField` objects to produce an `Interchange` object which can then be exported to formats understood by other molecular simulation engines. This extra step is needed to provide a clean interface between _applied_ parameters and engines. Note also that this step does not create an `openmm.system` under the hood; `ForceField.create_interchange` is an entirely in-memory conversion without calls to external engines or conversion tools." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Interchange with 7 collections, periodic topology with 27 atoms." - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "interchange = forcefield.create_interchange(topology)\n", - "interchange" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting to Amber and GROMACS files\n", - "\n", - "Once an `Interchange` object has been constructed, its API [can be used to export](https://docs.openforcefield.org/projects/interchange/en/stable/using/output.html) to files understood by GROMACS, Amber, and more." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "system.gro system.prmtop system_pointenergy.in\n", - "system.inpcrd system.top system_pointenergy.mdp\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/mattthompson/micromamba/envs/openff-toolkit-test/lib/python3.12/site-packages/openff/interchange/components/mdconfig.py:402: SwitchingFunctionNotImplementedWarning: A switching distance 8.0 angstrom was specified by the force field, but Amber does not implement a switching function. Using a hard cut-off instead. Non-bonded interactions will be affected.\n", - " warnings.warn(\n" - ] - } - ], - "source": [ - "# Export AMBER files.\n", - "interchange.to_amber(prefix=\"system\")\n", - "\n", - "# Export GROMACS files.\n", - "interchange.to_gromacs(prefix=\"system\")\n", - "\n", - "# List the produced input files\n", - "!ls system*" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Validating the conversion to Amber files\n", - "\n", - "The Interchange project includes functions that take in an `Interchange` object and call out to simulation engines to run single-point energy calculations (with no minimization or dynamics) for the purpose of validating the export layer with each engine. Under the hood, each of these functions calls API points like those used above while converting to files understood by each engine. These rely on having each engine installed and accessible in the current `$PATH`." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from openff.interchange.drivers import get_amber_energies, get_openmm_energies" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'Angle': ,\n", - " 'Bond': ,\n", - " 'Nonbonded': ,\n", - " 'Torsion': }\n" - ] - } - ], - "source": [ - "openmm_energies = get_openmm_energies(interchange)\n", - "pprint(openmm_energies.energies)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'Angle': ,\n", - " 'Bond': ,\n", - " 'Electrostatics': ,\n", - " 'Torsion': ,\n", - " 'vdW': }\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/mattthompson/micromamba/envs/openff-toolkit-test/lib/python3.12/site-packages/openff/interchange/components/mdconfig.py:402: SwitchingFunctionNotImplementedWarning: A switching distance 8.0 angstrom was specified by the force field, but Amber does not implement a switching function. Using a hard cut-off instead. Non-bonded interactions will be affected.\n", - " warnings.warn(\n" - ] - } - ], - "source": [ - "amber_energies = get_amber_energies(interchange)\n", - "pprint(amber_energies.energies)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Appendix: Validating the conversion to GROMACS and LAMMPS files\n", - "\n", - "If GROMACS and/or LAMMPS are installed on your machine, the same comparisons can also take place with those engines. They are available via `conda` by running a command like:\n", - "\n", - "```mamba install \"gromacs >=2021=nompi*\" lammps -c conda-forge```" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "from openff.interchange.drivers import get_gromacs_energies, get_lammps_energies" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "if which(\"lmp_serial\"):\n", - " pprint(get_lammps_energies(interchange).energies)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'Angle': ,\n", - " 'Bond': ,\n", - " 'Electrostatics': ,\n", - " 'RBTorsion': ,\n", - " 'Torsion': ,\n", - " 'vdW': }\n" - ] - } - ], - "source": [ - "if which(\"gmx\"):\n", - " pprint(get_gromacs_energies(interchange).energies)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, there is a helper function `get_summary_data` that will attempt to run drivers of each engine. A summary reported is prepared as a Pandas `DataFrame`." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/mattthompson/micromamba/envs/openff-toolkit-test/lib/python3.12/site-packages/openff/interchange/components/mdconfig.py:402: SwitchingFunctionNotImplementedWarning: A switching distance 8.0 angstrom was specified by the force field, but Amber does not implement a switching function. Using a hard cut-off instead. Non-bonded interactions will be affected.\n", - " warnings.warn(\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
BondAngleTorsionElectrostaticsvdWRBTorsion
OpenMM0.7287038.66086424.825477-15.2156469.658657NaN
Amber0.7288538.66088024.825346-15.2163719.666714NaN
GROMACS0.7286768.66089224.825478-15.2232049.6670510.0
\n", - "
" - ], - "text/plain": [ - " Bond Angle Torsion Electrostatics vdW RBTorsion\n", - "OpenMM 0.728703 8.660864 24.825477 -15.215646 9.658657 NaN\n", - "Amber 0.728853 8.660880 24.825346 -15.216371 9.666714 NaN\n", - "GROMACS 0.728676 8.660892 24.825478 -15.223204 9.667051 0.0" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from openff.interchange.drivers.all import get_summary_data\n", - "\n", - "get_summary_data(interchange)" - ] - } - ], - "metadata": { - "category": "parametrization_evaluation", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.8" - }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "state": { - "07a4b226726548a0ab47011379a2eda1": { - "model_module": "nglview-js-widgets", - "model_module_version": "3.0.6", - "model_name": "ColormakerRegistryModel", - "state": { - "_dom_classes": [], - "_model_module": "nglview-js-widgets", - "_model_module_version": "3.0.6", - "_model_name": "ColormakerRegistryModel", - "_msg_ar": [], - "_msg_q": [], - "_ready": false, - "_view_count": null, - "_view_module": "nglview-js-widgets", - "_view_module_version": "3.0.6", - "_view_name": "ColormakerRegistryView", - "layout": "IPY_MODEL_3fc7576c8c5b49a497c3d04fc4bf70c4", - "tabbable": null, - "tooltip": null - } - }, - "3fc7576c8c5b49a497c3d04fc4bf70c4": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "2.0.0", - "model_name": "LayoutModel", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "2.0.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "2.0.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border_bottom": null, - "border_left": null, - "border_right": null, - "border_top": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - } - }, - "version_major": 2, - "version_minor": 0 - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb b/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb index 4b7df39c6..b52e9eaed 100644 --- a/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb +++ b/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb @@ -80,7 +80,7 @@ "source": [ "ligand_molecule = Molecule.from_file(\"ligand.sdf\")\n", "\n", - "sage = ForceField(\"openff-2.2.0.offxml\")\n", + "sage = ForceField(\"openff-2.3.0.offxml\")\n", "\n", "ligand_system = sage.create_interchange(topology=ligand_molecule.to_topology())\n", "\n", diff --git a/examples/virtual_sites/vsite_showcase.ipynb b/examples/virtual_sites/vsite_showcase.ipynb index bb7b63cea..5df309efa 100644 --- a/examples/virtual_sites/vsite_showcase.ipynb +++ b/examples/virtual_sites/vsite_showcase.ipynb @@ -184,7 +184,7 @@ "\"\"\"\n", "\n", "# Load Sage and append our virtual sites\n", - "force_field = ForceField(\"openff-2.2.0.offxml\", vsite_offxml)" + "force_field = ForceField(\"openff-2.3.0.offxml\", vsite_offxml)" ] }, {