From 4d52587b6b998eb6b48e14a9720feba3357d1aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Pulido?= <2949729+ijpulidos@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:07:44 -0400 Subject: [PATCH] Tests for capped AAs (#92) --- feflow/mapping/protein_mutation.py | 38 ++-- feflow/protocols/__init__.py | 1 + feflow/protocols/protein_mutation.py | 25 +-- feflow/tests/conftest.py | 2 +- feflow/tests/data/capped_AAs/ALA_capped.pdb | 39 ++++ feflow/tests/data/capped_AAs/ASP_capped.pdb | 42 ++++ feflow/tests/data/capped_AAs/GLY_capped.pdb | 36 ++++ feflow/tests/data/capped_AAs/LEU_capped.pdb | 49 +++++ .../data/capped_AAs/ala_to_gly_mapping.json | 1 + .../data/capped_AAs/asp_to_leu_mapping.json | 1 + feflow/tests/test_protein_mutation.py | 192 +++++++++++++++++- 11 files changed, 387 insertions(+), 39 deletions(-) create mode 100644 feflow/tests/data/capped_AAs/ALA_capped.pdb create mode 100644 feflow/tests/data/capped_AAs/ASP_capped.pdb create mode 100644 feflow/tests/data/capped_AAs/GLY_capped.pdb create mode 100644 feflow/tests/data/capped_AAs/LEU_capped.pdb create mode 100644 feflow/tests/data/capped_AAs/ala_to_gly_mapping.json create mode 100644 feflow/tests/data/capped_AAs/asp_to_leu_mapping.json diff --git a/feflow/mapping/protein_mutation.py b/feflow/mapping/protein_mutation.py index ee2c7f0..5e5113d 100644 --- a/feflow/mapping/protein_mutation.py +++ b/feflow/mapping/protein_mutation.py @@ -1,6 +1,7 @@ """ Module with mapping objects that are useful for the protein mutation protocol. """ + import re from gufe import ProteinComponent from gufe.mapping import AtomMapping @@ -17,17 +18,18 @@ class ProteinMutationMapping(AtomMapping): :class:`.ProteinComponent` which stores the mapping as a dict of integers. """ + componentA: ProteinComponent componentB: ProteinComponent _mutation_spec: re.Match[regex_mut_str] _compA_to_compB: dict[int, int] def __init__( - self, - componentA: ProteinComponent, - componentB: ProteinComponent, - componentA_to_componentB: dict[int, int], - mutation_spec: re.Match[regex_mut_str], + self, + componentA: ProteinComponent, + componentB: ProteinComponent, + componentA_to_componentB: dict[int, int], + mutation_spec: re.Match[regex_mut_str], ): """ Parameters @@ -50,11 +52,13 @@ def __init__( nB = self.componentB.to_openmm_topology().getNumAtoms() for i, j in componentA_to_componentB.items(): if not (0 <= i < nA): - raise ValueError(f"Got invalid index for ComponentA ({i}); " - f"must be 0 <= n < {nA}") + raise ValueError( + f"Got invalid index for ComponentA ({i}); " f"must be 0 <= n < {nA}" + ) if not (0 <= j < nB): - raise ValueError(f"Got invalid index for ComponentB ({i}); " - f"must be 0 <= n < {nB}") + raise ValueError( + f"Got invalid index for ComponentB ({i}); " f"must be 0 <= n < {nB}" + ) self._compA_to_compB = componentA_to_componentB self._mutation_spec = mutation_spec @@ -69,13 +73,19 @@ def componentB_to_componentA(self) -> dict[int, int]: @property def componentA_unique(self): - return (i for i in range(self.componentA.to_openmm_topology().getNumAtoms()) - if i not in self._compA_to_compB) + return ( + i + for i in range(self.componentA.to_openmm_topology().getNumAtoms()) + if i not in self._compA_to_compB + ) @property def componentB_unique(self): - return (i for i in range(self.componentB.to_openmm_topology().getNumAtoms()) - if i not in self._compA_to_compB.values()) + return ( + i + for i in range(self.componentB.to_openmm_topology().getNumAtoms()) + if i not in self._compA_to_compB.values() + ) @property def mutation_spec(self): @@ -106,4 +116,4 @@ def _from_dict(cls, dct: dict): componentB=dct["componentB"], componentA_to_componentB=fixed, mutation_spec=dct["mutation_spec"], - ) \ No newline at end of file + ) diff --git a/feflow/protocols/__init__.py b/feflow/protocols/__init__.py index b7f7807..b8fb1f9 100644 --- a/feflow/protocols/__init__.py +++ b/feflow/protocols/__init__.py @@ -7,3 +7,4 @@ NonEquilibriumCyclingProtocol, NonEquilibriumCyclingProtocolResult, ) +from .protein_mutation import ProteinMutationProtocol diff --git a/feflow/protocols/protein_mutation.py b/feflow/protocols/protein_mutation.py index c0de77e..4ab1298 100644 --- a/feflow/protocols/protein_mutation.py +++ b/feflow/protocols/protein_mutation.py @@ -2,28 +2,9 @@ Implementation of protein mutation protocol based on Nonequilibrium Cycling, using OpenMM as MD engine. """ -from typing import Dict, Any -from gufe import ChemicalSystem, Context, ProtocolUnit, AtomMapping +from gufe.protocols import Protocol -class SetupUnit(ProtocolUnit): - """ - Initial unit of the protocol. Creates a hybrid topology for the protein mutation and - generates the OpenMM. - """ - def _execute(ctx: Context, *, state_a: ChemicalSystem, state_b: ChemicalSystem, mapping: AtomMapping, **inputs) -> Dict[str, Any]: - """ - - Parameters - ---------- - state_a - state_b - mapping - inputs - - Returns - ------- - - """ - return NotImplementedError \ No newline at end of file +class ProteinMutationProtocol(Protocol): + pass diff --git a/feflow/tests/conftest.py b/feflow/tests/conftest.py index 167c4d3..a17d4e4 100644 --- a/feflow/tests/conftest.py +++ b/feflow/tests/conftest.py @@ -50,7 +50,7 @@ def benzene_modifications(gufe_data_dir): # Components fixtures -@pytest.fixture +@pytest.fixture(scope="session") def solvent_comp(): yield gufe.SolventComponent(positive_ion="Na", negative_ion="Cl") diff --git a/feflow/tests/data/capped_AAs/ALA_capped.pdb b/feflow/tests/data/capped_AAs/ALA_capped.pdb new file mode 100644 index 0000000..d4f0d09 --- /dev/null +++ b/feflow/tests/data/capped_AAs/ALA_capped.pdb @@ -0,0 +1,39 @@ +REMARK 1 CREATED WITH OPENMM 7.7, 2022-08-08 +HETATM 1 H1 ACE 1 1 1.328 2.173 -0.000 1.00 0.00 H +HETATM 2 CH3 ACE 1 1 2.006 1.318 -0.000 1.00 0.00 C +HETATM 3 H2 ACE 1 1 2.634 1.352 0.890 1.00 0.00 H +HETATM 4 H3 ACE 1 1 2.634 1.352 -0.890 1.00 0.00 H +HETATM 5 C ACE 1 1 1.229 0.000 0.000 1.00 0.00 C +HETATM 6 O ACE 1 1 0.000 0.000 0.000 1.00 0.00 O +ATOM 7 N ALA 1 2 1.954 -1.121 -0.000 1.00 0.00 N +ATOM 8 H ALA 1 2 2.963 -1.070 -0.000 1.00 0.00 H +ATOM 9 CA ALA 1 2 1.337 -2.432 -0.001 1.00 0.00 C +ATOM 10 HA ALA 1 2 0.717 -2.542 -0.891 1.00 0.00 H +ATOM 11 CB ALA 1 2 2.391 -3.535 -0.001 1.00 0.00 C +ATOM 12 HB1 ALA 1 2 3.014 -3.443 0.889 1.00 0.00 H +ATOM 13 HB2 ALA 1 2 1.899 -4.507 -0.001 1.00 0.00 H +ATOM 14 HB3 ALA 1 2 3.014 -3.442 -0.891 1.00 0.00 H +ATOM 15 C ALA 1 2 0.461 -2.626 1.229 1.00 0.00 C +ATOM 16 O ALA 1 2 -0.621 -3.201 1.139 1.00 0.00 O +HETATM 17 N NME 1 3 0.933 -2.143 2.381 1.00 0.00 N +HETATM 18 H NME 1 3 1.829 -1.678 2.404 1.00 0.00 H +HETATM 19 C NME 1 3 0.194 -2.264 3.621 1.00 0.00 C +HETATM 20 H1 NME 1 3 -0.745 -2.786 3.436 1.00 0.00 H +HETATM 21 H2 NME 1 3 0.786 -2.827 4.344 1.00 0.00 H +HETATM 22 H3 NME 1 3 -0.014 -1.271 4.019 1.00 0.00 H +TER 23 NME 1 3 +CONECT 1 2 +CONECT 2 3 4 1 5 +CONECT 3 2 +CONECT 4 2 +CONECT 5 6 7 2 +CONECT 6 5 +CONECT 7 5 +CONECT 15 17 +CONECT 17 18 15 19 +CONECT 18 17 +CONECT 19 20 21 22 17 +CONECT 20 19 +CONECT 21 19 +CONECT 22 19 +END diff --git a/feflow/tests/data/capped_AAs/ASP_capped.pdb b/feflow/tests/data/capped_AAs/ASP_capped.pdb new file mode 100644 index 0000000..f65d072 --- /dev/null +++ b/feflow/tests/data/capped_AAs/ASP_capped.pdb @@ -0,0 +1,42 @@ +REMARK 1 CREATED WITH OPENMM 8.1.1, 2024-09-07 +CRYST1 21.573 21.573 21.573 90.00 90.00 90.00 P 1 1 +HETATM 1 C ACE A 1 -0.422 0.355 0.335 1.00 0.00 C +HETATM 2 O ACE A 1 -1.381 0.231 -0.410 1.00 0.00 O +HETATM 3 CH3 ACE A 1 -0.620 0.215 1.832 1.00 0.00 C +HETATM 4 H1 ACE A 1 -0.357 1.152 2.323 1.00 0.00 H +HETATM 5 H2 ACE A 1 -0.005 -0.601 2.210 1.00 0.00 H +HETATM 6 H3 ACE A 1 -1.670 -0.008 2.024 1.00 0.00 H +ATOM 7 N ASP A 2 0.787 0.621 -0.157 1.00 0.00 N +ATOM 8 H ASP A 2 0.859 0.517 -1.158 1.00 0.00 H +ATOM 9 CA ASP A 2 2.047 0.800 0.570 1.00 0.00 C +ATOM 10 HA ASP A 2 1.844 1.218 1.554 1.00 0.00 H +ATOM 11 CB ASP A 2 2.721 -0.570 0.745 1.00 0.00 C +ATOM 12 HB2 ASP A 2 2.848 -0.711 1.820 1.00 0.00 H +ATOM 13 HB3 ASP A 2 3.733 -0.505 0.342 1.00 0.00 H +ATOM 14 C ASP A 2 2.979 1.781 -0.171 1.00 0.00 C +ATOM 15 O ASP A 2 2.852 1.973 -1.378 1.00 0.00 O +ATOM 16 CG ASP A 2 2.114 -1.877 0.199 1.00 0.00 C +ATOM 17 OD1 ASP A 2 1.032 -1.872 -0.434 1.00 0.00 O +ATOM 18 OD2 ASP A 2 2.778 -2.921 0.392 1.00 0.00 O +HETATM 19 N NME A 3 3.929 2.385 0.555 1.00 0.00 N +HETATM 20 H NME A 3 3.986 2.172 1.540 1.00 0.00 H +HETATM 21 C NME A 3 4.899 3.328 0.000 1.00 0.00 C +HETATM 22 H1 NME A 3 5.524 2.821 -0.736 1.00 0.00 H +HETATM 23 H2 NME A 3 5.531 3.733 0.790 1.00 0.00 H +HETATM 24 H3 NME A 3 4.376 4.145 -0.497 1.00 0.00 H +TER 25 NME A 3 +CONECT 1 3 2 7 +CONECT 2 1 +CONECT 3 1 4 5 6 +CONECT 4 3 +CONECT 5 3 +CONECT 6 3 +CONECT 7 1 +CONECT 14 19 +CONECT 19 14 21 20 +CONECT 20 19 +CONECT 21 22 23 24 19 +CONECT 22 21 +CONECT 23 21 +CONECT 24 21 +END diff --git a/feflow/tests/data/capped_AAs/GLY_capped.pdb b/feflow/tests/data/capped_AAs/GLY_capped.pdb new file mode 100644 index 0000000..a2fbbe3 --- /dev/null +++ b/feflow/tests/data/capped_AAs/GLY_capped.pdb @@ -0,0 +1,36 @@ +REMARK 1 CREATED WITH OPENMM 8.1.1, 2024-09-26 +HETATM 1 H1 ACE A 1 1.328 2.173 0.000 1.00 0.00 H +HETATM 2 CH3 ACE A 1 2.006 1.318 0.000 1.00 0.00 C +HETATM 3 H2 ACE A 1 2.634 1.352 0.890 1.00 0.00 H +HETATM 4 H3 ACE A 1 2.634 1.352 -0.890 1.00 0.00 H +HETATM 5 C ACE A 1 1.229 0.000 0.000 1.00 0.00 C +HETATM 6 O ACE A 1 0.000 0.000 0.000 1.00 0.00 O +ATOM 7 N GLY A 2 1.954 -1.121 0.000 1.00 0.00 N +ATOM 8 H GLY A 2 3.108 -1.173 -0.285 1.00 0.00 H +ATOM 9 CA GLY A 2 1.337 -2.432 -0.001 1.00 0.00 C +ATOM 10 HA2 GLY A 2 2.093 -3.358 0.013 1.00 0.00 H +ATOM 11 HA3 GLY A 2 0.710 -2.575 -1.009 1.00 0.00 H +ATOM 12 C GLY A 2 0.461 -2.626 1.229 1.00 0.00 C +ATOM 13 O GLY A 2 -0.621 -3.201 1.139 1.00 0.00 O +HETATM 14 N NME A 3 0.933 -2.143 2.381 1.00 0.00 N +HETATM 15 H NME A 3 1.829 -1.678 2.404 1.00 0.00 H +HETATM 16 C NME A 3 0.194 -2.264 3.621 1.00 0.00 C +HETATM 17 H1 NME A 3 -0.745 -2.786 3.436 1.00 0.00 H +HETATM 18 H2 NME A 3 0.786 -2.827 4.344 1.00 0.00 H +HETATM 19 H3 NME A 3 -0.014 -1.271 4.019 1.00 0.00 H +TER 20 NME A 3 +CONECT 1 2 +CONECT 2 5 1 3 4 +CONECT 3 2 +CONECT 4 2 +CONECT 5 2 6 7 +CONECT 6 5 +CONECT 7 5 +CONECT 12 14 +CONECT 14 12 16 15 +CONECT 15 14 +CONECT 16 17 18 19 14 +CONECT 17 16 +CONECT 18 16 +CONECT 19 16 +END diff --git a/feflow/tests/data/capped_AAs/LEU_capped.pdb b/feflow/tests/data/capped_AAs/LEU_capped.pdb new file mode 100644 index 0000000..5f1d3da --- /dev/null +++ b/feflow/tests/data/capped_AAs/LEU_capped.pdb @@ -0,0 +1,49 @@ +REMARK 1 CREATED WITH OPENMM 8.1.1, 2024-09-26 +CRYST1 21.573 21.573 21.573 90.00 90.00 90.00 P 1 1 +HETATM 1 C ACE A 1 -0.422 0.355 0.335 1.00 0.00 C +HETATM 2 O ACE A 1 -1.381 0.231 -0.410 1.00 0.00 O +HETATM 3 CH3 ACE A 1 -0.620 0.215 1.832 1.00 0.00 C +HETATM 4 H1 ACE A 1 -0.357 1.152 2.323 1.00 0.00 H +HETATM 5 H2 ACE A 1 -0.005 -0.601 2.210 1.00 0.00 H +HETATM 6 H3 ACE A 1 -1.670 -0.008 2.024 1.00 0.00 H +ATOM 7 N LEU A 2 0.787 0.621 -0.157 1.00 0.00 N +ATOM 8 H LEU A 2 0.585 1.302 -1.114 1.00 0.00 H +ATOM 9 CA LEU A 2 2.047 0.800 0.570 1.00 0.00 C +ATOM 10 HA LEU A 2 1.872 1.402 1.585 1.00 0.00 H +ATOM 11 CB LEU A 2 2.721 -0.570 0.745 1.00 0.00 C +ATOM 12 HB2 LEU A 2 2.896 -0.707 1.921 1.00 0.00 H +ATOM 13 HB3 LEU A 2 3.802 -0.518 0.236 1.00 0.00 H +ATOM 14 C LEU A 2 2.979 1.781 -0.171 1.00 0.00 C +ATOM 15 O LEU A 2 2.852 1.973 -1.378 1.00 0.00 O +ATOM 16 CG LEU A 2 2.114 -1.877 0.199 1.00 0.00 C +ATOM 17 HG LEU A 2 1.155 -2.230 0.816 1.00 0.00 H +ATOM 18 CD1 LEU A 2 3.027 -3.075 0.432 1.00 0.00 C +ATOM 19 HD11 LEU A 2 3.670 -3.474 -0.502 1.00 0.00 H +ATOM 20 HD12 LEU A 2 3.864 -2.952 1.286 1.00 0.00 H +ATOM 21 HD13 LEU A 2 2.416 -4.046 0.795 1.00 0.00 H +ATOM 22 CD2 LEU A 2 1.603 -1.815 -1.240 1.00 0.00 C +ATOM 23 HD21 LEU A 2 0.588 -1.372 -1.700 1.00 0.00 H +ATOM 24 HD22 LEU A 2 2.443 -1.412 -1.995 1.00 0.00 H +ATOM 25 HD23 LEU A 2 1.412 -2.946 -1.601 1.00 0.00 H +HETATM 26 N NME A 3 3.929 2.385 0.555 1.00 0.00 N +HETATM 27 H NME A 3 3.986 2.172 1.540 1.00 0.00 H +HETATM 28 C NME A 3 4.899 3.328 0.000 1.00 0.00 C +HETATM 29 H1 NME A 3 5.524 2.821 -0.736 1.00 0.00 H +HETATM 30 H2 NME A 3 5.531 3.733 0.790 1.00 0.00 H +HETATM 31 H3 NME A 3 4.376 4.145 -0.497 1.00 0.00 H +TER 32 NME A 3 +CONECT 1 3 2 7 +CONECT 2 1 +CONECT 3 1 4 5 6 +CONECT 4 3 +CONECT 5 3 +CONECT 6 3 +CONECT 7 1 +CONECT 14 26 +CONECT 26 14 28 27 +CONECT 27 26 +CONECT 28 29 30 31 26 +CONECT 29 28 +CONECT 30 28 +CONECT 31 28 +END diff --git a/feflow/tests/data/capped_AAs/ala_to_gly_mapping.json b/feflow/tests/data/capped_AAs/ala_to_gly_mapping.json new file mode 100644 index 0000000..6f402e3 --- /dev/null +++ b/feflow/tests/data/capped_AAs/ala_to_gly_mapping.json @@ -0,0 +1 @@ +{"componentA": {"atoms": [[1, "1", 1, 0, " ", "H1", "ACE", 1, "N", 0], [6, "1", 2, 0, " ", "CH3", "ACE", 1, "N", 0], [1, "1", 3, 0, " ", "H2", "ACE", 1, "N", 0], [1, "1", 4, 0, " ", "H3", "ACE", 1, "N", 0], [6, "1", 5, 0, " ", "C", "ACE", 1, "N", 0], [8, "1", 6, 0, " ", "O", "ACE", 1, "N", 0], [7, "1", 7, 0, " ", "N", "ALA", 2, "N", 0], [1, "1", 8, 0, " ", "H", "ALA", 2, "N", 0], [6, "1", 9, 0, " ", "CA", "ALA", 2, "N", 0], [1, "1", 10, 0, " ", "HA", "ALA", 2, "N", 0], [6, "1", 11, 0, " ", "CB", "ALA", 2, "N", 0], [1, "1", 12, 0, " ", "HB1", "ALA", 2, "N", 0], [1, "1", 13, 0, " ", "HB2", "ALA", 2, "N", 0], [1, "1", 14, 0, " ", "HB3", "ALA", 2, "N", 0], [6, "1", 15, 0, " ", "C", "ALA", 2, "N", 0], [8, "1", 16, 0, " ", "O", "ALA", 2, "N", 0], [7, "1", 17, 0, " ", "N", "NME", 3, "N", 0], [1, "1", 18, 0, " ", "H", "NME", 3, "N", 0], [6, "1", 19, 0, " ", "C", "NME", 3, "N", 0], [1, "1", 20, 0, " ", "H1", "NME", 3, "N", 0], [1, "1", 21, 0, " ", "H2", "NME", 3, "N", 0], [1, "1", 22, 0, " ", "H3", "NME", 3, "N", 0]], "bonds": [[4, 1, "SINGLE", "N"], [4, 5, "DOUBLE", "N"], [1, 0, "SINGLE", "N"], [1, 2, "SINGLE", "N"], [1, 3, "SINGLE", "N"], [4, 6, "SINGLE", "N"], [14, 8, "SINGLE", "N"], [14, 15, "DOUBLE", "N"], [8, 10, "SINGLE", "N"], [8, 9, "SINGLE", "N"], [8, 6, "SINGLE", "N"], [10, 11, "SINGLE", "N"], [10, 12, "SINGLE", "N"], [10, 13, "SINGLE", "N"], [7, 6, "SINGLE", "N"], [14, 16, "SINGLE", "N"], [18, 19, "SINGLE", "N"], [18, 20, "SINGLE", "N"], [18, 21, "SINGLE", "N"], [18, 16, "SINGLE", "N"], [17, 16, "SINGLE", "N"]], "name": "", "conformers": ["\u0093NUMPY\u0001\u0000v\u0000{'descr': '\n\u00d7\u00a3p=\u00da\u00bf\u00d7\u00a3p=\n\u00d7\u00e3\u00bf\u0086\u00ebQ\u00b8\u001e\u0085\u00cb?\u001eZd;\u00dfO\u00fd?\r\u0002+\u0087\u0016\u00d9\u00d6\u00bf;\u00dfO\u008d\u0097n\u00f2?/\u00dd$\u0006\u0081\u0095\u0002@{\u0014\u00aeG\u00e1zt\u00bf\b\u00ac\u001cZd;\u00e3\u00bf\u00aeG\u00e1z\u0014\u00ae\u0001@\u00b9\u001e\u0085\u00ebQ\u00b8\u00fa\u00bf\u00fc\u00a9\u00f1\u00d2Mb\u0080\u00bf\u00fe\u00d4x\u00e9&1\u0000@\u00c9v\u00be\u009f\u001a/\u00e9?\u00ac\u001cZd;\u00df\u00e3?\u0080j\u00bct\u0093\u0018\u00c4\u00bf\u00b0rh\u0091\u00ed|\u00eb?%\u0006\u0081\u0095C\u008b\u00e0?\u00baI\f\u0002+\u0087\u00f2\u00bf\u00c7K7\u0089A`\u0000@\u009b\u0099\u0099\u0099\u0099\u0099\u00e9?=\n\u00d7\u00a3p=\u00e2?\u001b/\u00dd$\u0006\u0081\u00fd?\u00b0rh\u0091\u00ed|\u00f3?w\u00be\u009f\u001a/\u00dd\u00f8?\u00f8S\u00e3\u00a5\u009b\u00c4\u0005@=\n\u00d7\u00a3p=\u00e2\u00bf\u00d7\u00a3p=\n\u00d7\u00e7?b\u0010X9\u00b4\u00c8\u0006@\u008d\u0097n\u0012\u0083\u00c0\u00e6\u00bf \u0085\u00ebQ\u00b8\u001e\u00fd?w\u00be\u009f\u001a/\u00dd\r@)\\\u008f\u00c2\u00f5(\u00e0\u00bf\u0017\u00d9\u00ce\u00f7S\u00e3\u00d5?\u00a2E\u00b6\u00f3\u00fd\u00d4\u0007@\u00e6\u00d0\"\u00db\u00f9~\u00fc?\u0017\u00d9\u00ce\u00f7S\u00e3\u00c5\u00bf8\u0089A`\u00e5\u00d0\u0006@\u00c6 \u00b0rh\u0091\u00ff?@5^\u00baI\f\u00f6\u00bf\u00b6\u00f3\u00fd\u00d4x\u00e9\u0000@\u00d5x\u00e9&1\b\u00fe\u00bfF\u00b6\u00f3\u00fd\u00d4x\u00c9?P\u008d\u0097n\u0012\u0083\u00f0?\u00c2\u00ca\u00a1E\u00b6\u00f3\u00fd\u00bf-\u00b2\u009d\u00ef\u00a7\u00c6\u00db\u00bf\u00d3Mb\u0010X9\u0006@\u0091\u00ed|?5^\u0007\u00c0K\f\u0002+\u0087\u0016\u00d9?<\u00dfO\u008d\u0097n\u000f@\u0014\u00aeG\u00e1z\u0014\u0003@\u00c3\u00f5(\\\u008f\u00c2\u00e1?\u0018\u00d9\u00ce\u00f7S\u00e3\u000f@\u00c7K7\u0089A`\u0001@\u00a5p=\n\u00d7\u00a3\u00f8?\u007fj\u00bct\u0093\u0098\u0013@9\u00b4\u00c8v\u00be\u009f\n@\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u007fj\u00bct\u0093\u0018\u0016@\u00c5 \u00b0rh\u0091\u0006@Zd;\u00dfO\u008d\u00e7\u00bf:\u00b4\u00c8v\u00be\u001f\u0016@w\u00be\u009f\u001a/\u00dd\r@I\u00e1z\u0014\u00aeG\u00e9?\u001b/\u00dd$\u0006\u0081\u0011@\u0014\u00aeG\u00e1z\u0094\u0010@\u0002+\u0087\u0016\u00d9\u00ce\u00df\u00bf"], "__qualname__": "ProteinComponent", "__module__": "gufe.components.proteincomponent", ":version:": 1}, "componentB": {"atoms": [[6, "A", 1, 0, " ", "C", "ACE", 1, "N", 0], [8, "A", 2, 0, " ", "O", "ACE", 1, "N", 0], [6, "A", 3, 0, " ", "CH3", "ACE", 1, "N", 0], [1, "A", 4, 0, " ", "H1", "ACE", 1, "N", 0], [1, "A", 5, 0, " ", "H2", "ACE", 1, "N", 0], [1, "A", 6, 0, " ", "H3", "ACE", 1, "N", 0], [7, "A", 7, 0, " ", "N", "LEU", 2, "N", 0], [1, "A", 8, 0, " ", "H", "LEU", 2, "N", 0], [6, "A", 9, 0, " ", "CA", "LEU", 2, "N", 0], [1, "A", 10, 0, " ", "HA", "LEU", 2, "N", 0], [6, "A", 11, 0, " ", "CB", "LEU", 2, "N", 0], [1, "A", 12, 0, " ", "HB2", "LEU", 2, "N", 0], [1, "A", 13, 0, " ", "HB3", "LEU", 2, "N", 0], [6, "A", 14, 0, " ", "C", "LEU", 2, "N", 0], [8, "A", 15, 0, " ", "O", "LEU", 2, "N", 0], [6, "A", 16, 0, " ", "CG", "LEU", 2, "N", 0], [1, "A", 17, 0, " ", "HG", "LEU", 2, "N", 0], [6, "A", 18, 0, " ", "CD1", "LEU", 2, "N", 0], [1, "A", 19, 0, " ", "HD11", "LEU", 2, "N", 0], [1, "A", 20, 0, " ", "HD12", "LEU", 2, "N", 0], [1, "A", 21, 0, " ", "HD13", "LEU", 2, "N", 0], [6, "A", 22, 0, " ", "CD2", "LEU", 2, "N", 0], [1, "A", 23, 0, " ", "HD21", "LEU", 2, "N", 0], [1, "A", 24, 0, " ", "HD22", "LEU", 2, "N", 0], [1, "A", 25, 0, " ", "HD23", "LEU", 2, "N", 0], [7, "A", 26, 0, " ", "N", "NME", 3, "N", 0], [1, "A", 27, 0, " ", "H", "NME", 3, "N", 0], [6, "A", 28, 0, " ", "C", "NME", 3, "N", 0], [1, "A", 29, 0, " ", "H1", "NME", 3, "N", 0], [1, "A", 30, 0, " ", "H2", "NME", 3, "N", 0], [1, "A", 31, 0, " ", "H3", "NME", 3, "N", 0]], "bonds": [[0, 2, "SINGLE", "N"], [0, 1, "DOUBLE", "N"], [2, 3, "SINGLE", "N"], [2, 4, "SINGLE", "N"], [2, 5, "SINGLE", "N"], [0, 6, "SINGLE", "N"], [13, 8, "SINGLE", "N"], [13, 14, "DOUBLE", "N"], [8, 10, "SINGLE", "N"], [8, 9, "SINGLE", "N"], [8, 6, "SINGLE", "N"], [10, 15, "SINGLE", "N"], [10, 11, "SINGLE", "N"], [10, 12, "SINGLE", "N"], [17, 15, "SINGLE", "N"], [17, 18, "SINGLE", "N"], [17, 19, "SINGLE", "N"], [17, 20, "SINGLE", "N"], [21, 15, "SINGLE", "N"], [21, 22, "SINGLE", "N"], [21, 23, "SINGLE", "N"], [21, 24, "SINGLE", "N"], [15, 16, "SINGLE", "N"], [7, 6, "SINGLE", "N"], [13, 25, "SINGLE", "N"], [27, 28, "SINGLE", "N"], [27, 29, "SINGLE", "N"], [27, 30, "SINGLE", "N"], [27, 25, "SINGLE", "N"], [26, 25, "SINGLE", "N"]], "name": "", "conformers": ["\u0093NUMPY\u0001\u0000v\u0000{'descr': '\n\u00d7\u00a3p=\u00da\u00bf\u00d7\u00a3p=\n\u00d7\u00e3\u00bf\u0086\u00ebQ\u00b8\u001e\u0085\u00cb?\u001eZd;\u00dfO\u00fd?\r\u0002+\u0087\u0016\u00d9\u00d6\u00bf;\u00dfO\u008d\u0097n\u00f2?/\u00dd$\u0006\u0081\u0095\u0002@{\u0014\u00aeG\u00e1zt\u00bf\b\u00ac\u001cZd;\u00e3\u00bf\u00aeG\u00e1z\u0014\u00ae\u0001@\u00b9\u001e\u0085\u00ebQ\u00b8\u00fa\u00bf\u00fc\u00a9\u00f1\u00d2Mb\u0080\u00bf\u00fe\u00d4x\u00e9&1\u0000@\u00c9v\u00be\u009f\u001a/\u00e9?\u00ac\u001cZd;\u00df\u00e3?\u0080j\u00bct\u0093\u0018\u00c4\u00bf\u00b8\u001e\u0085\u00ebQ\u00b8\u00e2?\u00a2E\u00b6\u00f3\u00fd\u00d4\u00f4?m\u00e7\u00fb\u00a9\u00f1\u00d2\u00f1\u00bf\u00c7K7\u0089A`\u0000@\u009b\u0099\u0099\u0099\u0099\u0099\u00e9?=\n\u00d7\u00a3p=\u00e2?\u00c2\u00ca\u00a1E\u00b6\u00f3\u00fd?;\u00dfO\u008d\u0097n\u00f6?\\\u008f\u00c2\u00f5(\\\u00f9?\u00f8S\u00e3\u00a5\u009b\u00c4\u0005@=\n\u00d7\u00a3p=\u00e2\u00bf\u00d7\u00a3p=\n\u00d7\u00e7?_\u00baI\f\u0002+\u0007@9\u00b4\u00c8v\u00be\u009f\u00e6\u00bf$\u00db\u00f9~j\u00bc\u00fe?\u00d2\"\u00db\u00f9~j\u000e@\u00fa~j\u00bct\u0093\u00e0\u00bfh\u0091\u00ed|?5\u00ce?\u00a2E\u00b6\u00f3\u00fd\u00d4\u0007@\u00e6\u00d0\"\u00db\u00f9~\u00fc?\u0017\u00d9\u00ce\u00f7S\u00e3\u00c5\u00bf8\u0089A`\u00e5\u00d0\u0006@\u00c6 \u00b0rh\u0091\u00ff?@5^\u00baI\f\u00f6\u00bf\u00b6\u00f3\u00fd\u00d4x\u00e9\u0000@\u00d5x\u00e9&1\b\u00fe\u00bfF\u00b6\u00f3\u00fd\u00d4x\u00c9?{\u0014\u00aeG\u00e1z\u00f2?\u00d7\u00a3p=\n\u00d7\u0001\u00c0\u00ea&1\b\u00ac\u001c\u00ea?\u009e\u00ef\u00a7\u00c6K7\b@\u009b\u0099\u0099\u0099\u0099\u0099\b\u00c0\u00da\u00ce\u00f7S\u00e3\u00a5\u00db?\\\u008f\u00c2\u00f5(\\\r@\u0098n\u0012\u0083\u00c0\u00ca\u000b\u00c0\u00aa\u00f1\u00d2Mb\u0010\u00e0\u00bf\u00b7\u00f3\u00fd\u00d4x\u00e9\u000e@\u0004V\u000e-\u00b2\u009d\u0007\u00c0\u00fb~j\u00bct\u0093\u00f4?\u0087\u0016\u00d9\u00ce\u00f7S\u0003@\u00cav\u00be\u009f\u001a/\u0010\u00c0r=\n\u00d7\u00a3p\u00e9?\u00d9\u00ce\u00f7S\u00e3\u00a5\u00f9?\n\u00d7\u00a3p=\n\u00fd\u00bf\u00d7\u00a3p=\n\u00d7\u00f3\u00bf7\u0089A`\u00e5\u00d0\u00e2?\u00c1\u00ca\u00a1E\u00b6\u00f3\u00f5\u00bf433333\u00fb\u00bf%\u0006\u0081\u0095C\u008b\u0003@d;\u00dfO\u008d\u0097\u00f6\u00bf\u00ecQ\u00b8\u001e\u0085\u00eb\u00ff\u00bfd;\u00dfO\u008d\u0097\u00f6?\u00c5 \u00b0rh\u0091\u0007\u00c0\u0005V\u000e-\u00b2\u009d\u00f9\u00bf<\u00dfO\u008d\u0097n\u000f@\u0014\u00aeG\u00e1z\u0014\u0003@\u00c3\u00f5(\\\u008f\u00c2\u00e1?\u0018\u00d9\u00ce\u00f7S\u00e3\u000f@\u00c7K7\u0089A`\u0001@\u00a5p=\n\u00d7\u00a3\u00f8?\u007fj\u00bct\u0093\u0098\u0013@9\u00b4\u00c8v\u00be\u009f\n@\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u007fj\u00bct\u0093\u0018\u0016@\u00c5 \u00b0rh\u0091\u0006@Zd;\u00dfO\u008d\u00e7\u00bf:\u00b4\u00c8v\u00be\u001f\u0016@w\u00be\u009f\u001a/\u00dd\r@I\u00e1z\u0014\u00aeG\u00e9?\u001b/\u00dd$\u0006\u0081\u0011@\u0014\u00aeG\u00e1z\u0094\u0010@\u0002+\u0087\u0016\u00d9\u00ce\u00df\u00bf"], "__qualname__": "ProteinComponent", "__module__": "gufe.components.proteincomponent", ":version:": 1}, "componentA_to_componentB": {"3": 3, "4": 4, "5": 5, "7": 7, "9": 9, "11": 11, "12": 12, "19": 26, "21": 28, "22": 29, "23": 30, "0": 0, "1": 1, "2": 2, "6": 6, "8": 8, "10": 10, "13": 13, "14": 14, "15": 15, "17": 17, "18": 25, "20": 27}, "annotations": "{}", "__qualname__": "LigandAtomMapping", "__module__": "gufe.mapping.ligandatommapping", ":version:": 1} \ No newline at end of file diff --git a/feflow/tests/test_protein_mutation.py b/feflow/tests/test_protein_mutation.py index 96e27e1..b0b3237 100644 --- a/feflow/tests/test_protein_mutation.py +++ b/feflow/tests/test_protein_mutation.py @@ -1,6 +1,194 @@ """Test related to the protein mutation protocol and utility functions""" +import json +from importlib.resources import files +from pathlib import Path + +import pytest +from gufe import ProteinComponent, ChemicalSystem, ProtocolDAGResult +from gufe.protocols.protocoldag import execute_DAG +from feflow.protocols import ProteinMutationProtocol + + +# Fixtures +@pytest.fixture(scope="session") +def ala_capped(): + """ProteinComponent for Alanine residue capped by ACE and NME.""" + input_pdb = str(files("feflow.tests.data.capped_AAs").joinpath("ALA_capped.pdb")) + protein_comp = ProteinComponent.from_pdb_file(input_pdb) + return protein_comp + + +@pytest.fixture(scope="session") +def gly_capped(): + """ProteinComponent for Glycine residue capped by ACE and NME""" + input_pdb = str(files("feflow.tests.data.capped_AAs").joinpath("GLY_capped.pdb")) + protein_comp = ProteinComponent.from_pdb_file(input_pdb) + return protein_comp + + +@pytest.fixture(scope="session") +def asp_capped(): + """ProteinComponent for Aspartic Acid residue capped by ACE and NME. + This is meant to be used for testing charge transformations.""" + input_pdb = str(files("feflow.tests.data.capped_AAs").joinpath("ASP_capped.pdb")) + protein_comp = ProteinComponent.from_pdb_file(input_pdb) + return protein_comp + + +@pytest.fixture(scope="session") +def leu_capped(): + """ProteinComponent for Leucine residue capped by ACE and NME. + This is meant to be used for testing charge transformations.""" + input_pdb = str(files("feflow.tests.data.capped_AAs").joinpath("LEU_capped.pdb")) + protein_comp = ProteinComponent.from_pdb_file(input_pdb) + return protein_comp + + +@pytest.fixture(scope="session") +def ala_capped_system(ala_capped, solvent_comp): + """Solvated capped Alanine ChemicalSystem""" + return ChemicalSystem({"protein": ala_capped, "solvent": solvent_comp}) + + +@pytest.fixture(scope="session") +def gly_capped_system(gly_capped, solvent_comp): + """Solvated capped Alanine ChemicalSystem""" + return ChemicalSystem({"protein": gly_capped, "solvent": solvent_comp}) + + +@pytest.fixture(scope="session") +def asp_capped_system(asp_capped, solvent_comp): + """Solvated capped Aspartic acid ChemicalSystem""" + return ChemicalSystem({"protein": asp_capped, "solvent": solvent_comp}) + + +@pytest.fixture(scope="session") +def leu_capped_system(leu_capped, solvent_comp): + """Solvated capped Leucine ChemicalSystem""" + return ChemicalSystem({"protein": leu_capped, "solvent": solvent_comp}) + + +@pytest.fixture(scope="session") +def ala_to_gly_mapping(ala_capped, gly_capped): + """Mapping from ALA to GLY (capped)""" + from gufe import LigandAtomMapping + + input_file = str( + files("feflow.tests.data.capped_AAs").joinpath("ala_to_gly_mapping.json") + ) + with open(input_file) as in_file: + mapping = LigandAtomMapping.from_dict(json.load(in_file)) + return mapping + + +@pytest.fixture(scope="session") +def asp_to_leu_mapping(asp_capped, leu_capped): + """Mapping from ASP to LEU (capped). Charge transformation.""" + from gufe import LigandAtomMapping + + input_file = str( + files("feflow.tests.data.capped_AAs").joinpath("asp_to_leu_mapping.json") + ) + with open(input_file) as in_file: + mapping = LigandAtomMapping.from_dict(json.load(in_file)) + return mapping + class TestProtocolMutation: - def test_protocol(self): - return NotImplementedError + @pytest.fixture(scope="class") + def short_settings_protein_mutation(self): + settings = ProteinMutationProtocol.default_settings() + + settings.integrator_settings.equlibrium_steps = 1000 + settings.integrator_settings.nonequlibrium_steps = 1000 + settings.work_save_frequency = 50 + settings.traj_save_frequency = 250 + settings.num_cycles = 5 + settings.engine_settings.compute_platform = "CPU" + + return settings + + @pytest.fixture(scope="class") + def protocol_short(self, short_settings_protein_mutation): + return ProteinMutationProtocol(settings=short_settings_protein_mutation) + + @pytest.fixture(scope="class") + def protocol_ala_to_gly_result( + self, + protocol_short, + ala_capped_system, + gly_capped_system, + ala_to_gly_mapping, + tmpdir, + ): + dag = protocol_short.create( + stateA=ala_capped_system, + stateB=gly_capped_system, + name="Short vacuum transformation", + mapping=ala_to_gly_mapping, + ) + + with tmpdir.as_cwd(): + shared = Path("shared") + shared.mkdir() + + scratch = Path("scratch") + scratch.mkdir() + + dagresult: ProtocolDAGResult = execute_DAG( + dag, shared_basedir=shared, scratch_basedir=scratch + ) + + return protocol_short, dag, dagresult + + @pytest.fixture(scope="class") + def protocol_asp_to_leu_result( + self, + protocol_short, + asp_capped_system, + leu_capped_system, + asp_to_leu_mapping, + tmpdir, + ): + dag = protocol_short.create( + stateA=ala_capped_system, + stateB=gly_capped_system, + name="Short vacuum transformation", + mapping=ala_to_gly_mapping, + ) + + with tmpdir.as_cwd(): + shared = Path("shared") + shared.mkdir() + + scratch = Path("scratch") + scratch.mkdir() + + dagresult: ProtocolDAGResult = execute_DAG( + dag, shared_basedir=shared, scratch_basedir=scratch + ) + + return protocol_short, dag, dagresult + + def test_ala_to_gly_execute(self, protocol_ala_to_gly_result): + """Takes a protocol result from an executed DAG and checks the OK status + as well as the name of the resulting unit.""" + protocol, dag, dagresult = protocol_ala_to_gly_result + + assert dagresult.ok() + + # the FinishUnit will always be the last to execute + finishresult = dagresult.protocol_unit_results[-1] + assert finishresult.name == "result" + + def test_asp_to_leu_execute(self, protocol_asp_to_leu_result): + """Takes a protocol result from an executed DAG and checks the OK status + as well as the name of the resulting unit. Charge transformation case.""" + protocol, dag, dagresult = protocol_asp_to_leu_result + + assert dagresult.ok() + + # the FinishUnit will always be the last to execute + finishresult = dagresult.protocol_unit_results[-1] + assert finishresult.name == "result"