From f869f73e32229e74e8ae018bbd55531b2bede8ad Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Mon, 4 Dec 2023 22:17:13 -0600 Subject: [PATCH] Use new QCArchive APIs --- devtools/conda-envs/dev.yaml | 8 ++++---- ibstore/_db.py | 4 ++-- ibstore/_forcefields.py | 8 ++++---- ibstore/_session.py | 4 ++-- ibstore/_tests/unit_tests/test_forcefields.py | 4 ++++ ibstore/_tests/unit_tests/test_models.py | 2 +- ibstore/analysis.py | 6 +++--- ibstore/models.py | 11 +++++------ 8 files changed, 25 insertions(+), 22 deletions(-) diff --git a/devtools/conda-envs/dev.yaml b/devtools/conda-envs/dev.yaml index 26deb59..1c1f229 100644 --- a/devtools/conda-envs/dev.yaml +++ b/devtools/conda-envs/dev.yaml @@ -1,21 +1,21 @@ name: ib-dev channels: - - conda-forge - openeye + - conda-forge dependencies: - python - openff-toolkit =0.14.3 - - openff-qcsubmit + - openff-qcsubmit =0.50.1 - openmmforcefields - smirnoff-plugins =2023.08.0 - - espaloma + # espaloma =0.3 - ipython - ipdb - pre-commit - - openeye-toolkits + - openeye::openeye-toolkits - rich - pytest diff --git a/ibstore/_db.py b/ibstore/_db.py index 55c8a5f..033fc25 100644 --- a/ibstore/_db.py +++ b/ibstore/_db.py @@ -20,7 +20,7 @@ class DBQMConformerRecord(DBBase): id = Column(Integer, primary_key=True, index=True) parent_id = Column(Integer, ForeignKey("molecules.id"), nullable=False, index=True) - qcarchive_id = Column(String(20), nullable=False) + qcarchive_id = Column(Integer, nullable=False) mapped_smiles = Column(String, nullable=False) coordinates = Column(PickleType, nullable=False) @@ -33,7 +33,7 @@ class DBMMConformerRecord(DBBase): id = Column(Integer, primary_key=True, index=True) parent_id = Column(Integer, ForeignKey("molecules.id"), nullable=False, index=True) - qcarchive_id = Column(String(20), nullable=False) + qcarchive_id = Column(Integer, nullable=False) force_field = Column(String, nullable=False) mapped_smiles = Column(String, nullable=False) diff --git a/ibstore/_forcefields.py b/ibstore/_forcefields.py index 3f91ac4..8a05d16 100644 --- a/ibstore/_forcefields.py +++ b/ibstore/_forcefields.py @@ -73,7 +73,7 @@ def _espaloma(molecule: Molecule, force_field_name: str) -> openmm.System: espaloma.graphs.deploy.openmm_system_from_graph, where it will be appended with .offxml. Raises a ValueError if there is no dash in force_field_name. """ - import espaloma as esp + import espaloma if not force_field_name.startswith("espaloma"): raise NotImplementedError(f"Force field {force_field_name} not implemented.") @@ -85,8 +85,8 @@ def _espaloma(molecule: Molecule, force_field_name: str) -> openmm.System: else: ff = ff[0] - mol_graph = esp.Graph(molecule) - model = esp.get_model("latest") + mol_graph = espaloma.Graph(molecule) + model = espaloma.get_model("latest") model(mol_graph.heterograph) - return esp.graphs.deploy.openmm_system_from_graph(mol_graph, forcefield=ff) + return espaloma.graphs.deploy.openmm_system_from_graph(mol_graph, forcefield=ff) diff --git a/ibstore/_session.py b/ibstore/_session.py index 463201b..c2228c5 100644 --- a/ibstore/_session.py +++ b/ibstore/_session.py @@ -187,7 +187,7 @@ def store_qm_conformer_record( def _qm_conformer_already_exists( self, - qcarchive_id: str, + qcarchive_id: int, ) -> bool: records = self.db.query( DBQMConformerRecord.qcarchive_id, @@ -214,7 +214,7 @@ def store_mm_conformer_record( def _mm_conformer_already_exists( self, - qcarchive_id: str, + qcarchive_id: int, force_field: str, ) -> bool: records = ( diff --git a/ibstore/_tests/unit_tests/test_forcefields.py b/ibstore/_tests/unit_tests/test_forcefields.py index 8036bdd..60a247d 100644 --- a/ibstore/_tests/unit_tests/test_forcefields.py +++ b/ibstore/_tests/unit_tests/test_forcefields.py @@ -30,6 +30,8 @@ def test_gaff_unsupported(molecule): def test_espaloma_basic(molecule): + pytest.importorskip("espaloma") + system = _espaloma(molecule, "espaloma-openff_unconstrained-2.1.0") assert isinstance(system, openmm.System) @@ -37,5 +39,7 @@ def test_espaloma_basic(molecule): def test_espaloma_unsupported(molecule): + pytest.importorskip("espaloma") + with pytest.raises(NotImplementedError): _espaloma(molecule, "foo") diff --git a/ibstore/_tests/unit_tests/test_models.py b/ibstore/_tests/unit_tests/test_models.py index bb3043e..419a89a 100644 --- a/ibstore/_tests/unit_tests/test_models.py +++ b/ibstore/_tests/unit_tests/test_models.py @@ -26,7 +26,7 @@ def test_load_from_qcsubmit(small_collection): assert molecule_record.inchi_key == ichi_key assert isinstance(qm_conformer, QMConformerRecord) - assert qm_conformer.energy == qc_record.get_final_energy() * hartree2kcalmol + assert qm_conformer.energy == qc_record.energies[-1] * hartree2kcalmol assert qm_conformer.qcarchive_id == qc_record.id assert numpy.allclose( qm_conformer.coordinates, diff --git a/ibstore/analysis.py b/ibstore/analysis.py index 295295d..e17db1b 100644 --- a/ibstore/analysis.py +++ b/ibstore/analysis.py @@ -7,7 +7,7 @@ class DDE(ImmutableModel): - qcarchive_id: str + qcarchive_id: int force_field: str difference: float @@ -25,7 +25,7 @@ def to_csv(self, path: str): class RMSD(ImmutableModel): - qcarchive_id: str + qcarchive_id: int force_field: str rmsd: float @@ -43,7 +43,7 @@ def to_csv(self, path: str): class TFD(ImmutableModel): - qcarchive_id: str + qcarchive_id: int force_field: str tfd: float diff --git a/ibstore/models.py b/ibstore/models.py index 322e2ba..eb55dd1 100644 --- a/ibstore/models.py +++ b/ibstore/models.py @@ -1,9 +1,8 @@ -from typing import TypeVar +from typing import Any, TypeVar import qcelemental from openff.toolkit import Molecule from pydantic import Field -from qcportal.models.records import OptimizationRecord from ibstore._base.array import Array from ibstore._base.base import ImmutableModel @@ -26,7 +25,7 @@ class QMConformerRecord(Record): ..., description="The ID of the molecule in the database", ) - qcarchive_id: str = Field( + qcarchive_id: int = Field( ..., description="The ID of the molecule in the QCArchive database", ) @@ -50,7 +49,7 @@ def from_qcarchive_record( cls, molecule_id: int, mapped_smiles: str, - qc_record: OptimizationRecord, + qc_record: Any, # qcportal.optimization.OptimizationRecord ? coordinates, ): return cls( @@ -58,7 +57,7 @@ def from_qcarchive_record( qcarchive_id=qc_record.id, mapped_smiles=mapped_smiles, coordinates=coordinates, - energy=qc_record.get_final_energy() * hartree2kcalmol, + energy=qc_record.energies[-1] * hartree2kcalmol, ) @@ -67,7 +66,7 @@ class MMConformerRecord(Record): ..., description="The ID of the molecule in the database", ) - qcarchive_id: str = Field( + qcarchive_id: int = Field( ..., description="The ID of the molecule in the QCArchive database that this conformer corresponds to", )