diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a5debbc..29b8ace 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -58,7 +58,7 @@ jobs: - name: "Run tests" run: | - pytest -n auto -v --cov=openfe_analysis --cov-report=xml --durations=10 + pytest -v --cov=openfe_analysis --cov-report=xml --durations=10 - name: codecov if: ${{ github.repository == 'OpenFreeEnergy/openfe_analysis' diff --git a/environment.yml b/environment.yml index 2a15530..2815e04 100644 --- a/environment.yml +++ b/environment.yml @@ -4,7 +4,7 @@ channels: dependencies: - click - MDAnalysis - - netCDF4 + - netCDF4 <1.7.1 - openff-units - pip - tqdm diff --git a/src/openfe_analysis/reader.py b/src/openfe_analysis/reader.py index b7677bc..884550b 100644 --- a/src/openfe_analysis/reader.py +++ b/src/openfe_analysis/reader.py @@ -193,5 +193,7 @@ def _reopen(self): self._frame_index = -1 def close(self): - if self._dataset_owner: - self._dataset.close() + if self._dataset is not None: + if self._dataset_owner: + self._dataset.close() + self._dataset = None diff --git a/src/openfe_analysis/rmsd.py b/src/openfe_analysis/rmsd.py index 7d2af13..b7243d6 100644 --- a/src/openfe_analysis/rmsd.py +++ b/src/openfe_analysis/rmsd.py @@ -179,6 +179,8 @@ def gather_rms_data( output["time(ps)"] = list(np.arange(len(u.trajectory))[::skip] * u.trajectory.dt) + ds.close() + return output diff --git a/src/openfe_analysis/tests/conftest.py b/src/openfe_analysis/tests/conftest.py index 5fa2db4..a434e1d 100644 --- a/src/openfe_analysis/tests/conftest.py +++ b/src/openfe_analysis/tests/conftest.py @@ -3,6 +3,16 @@ import pathlib import pooch import pytest +import urllib.request + + +try: + urllib.request.urlopen('https://www.google.com') +except: # -no-cov- + HAS_INTERNET = False +else: + HAS_INTERNET = True + POOCH_CACHE = pooch.os_cache("openfe_analysis") ZENODO_RBFE_DATA = pooch.create( @@ -12,6 +22,7 @@ "openfe_analysis_simulation_output.tar.gz":"md5:09752f2c4e5b7744d8afdee66dbd1414", "openfe_analysis_skipped.tar.gz": "md5:3840d044299caacc4ccd50e6b22c0880", }, + retry_if_failed=5, ) @pytest.fixture(scope="session") @@ -46,7 +57,7 @@ def hybrid_system_skipped_pdb(rbfe_skipped_data_dir)->pathlib.Path: return rbfe_skipped_data_dir/"hybrid_system.pdb" -@pytest.fixture(scope="session") +@pytest.fixture(scope='session') def mcmc_serialized(): return ( "_serialized__class_name: LangevinDynamicsMove\n" diff --git a/src/openfe_analysis/tests/test_reader.py b/src/openfe_analysis/tests/test_reader.py index 6cef163..2da246e 100644 --- a/src/openfe_analysis/tests/test_reader.py +++ b/src/openfe_analysis/tests/test_reader.py @@ -105,6 +105,8 @@ def test_universe_creation(simulation_nc, hybrid_system_pdb): ) assert_allclose(u.dimensions, [82.191055, 82.191055, 82.191055, 90.0, 90.0, 90.0]) + u.trajectory.close() + def test_universe_from_nc_file(simulation_nc, hybrid_system_pdb): ds = nc.Dataset(simulation_nc) @@ -116,6 +118,7 @@ def test_universe_from_nc_file(simulation_nc, hybrid_system_pdb): assert len(u.atoms) == 4782 assert len(u.trajectory) == 501 assert u.trajectory.dt == pytest.approx(1.0) + ds.close() def test_universe_creation_noconversion(simulation_nc, hybrid_system_pdb): @@ -134,6 +137,7 @@ def test_universe_creation_noconversion(simulation_nc, hybrid_system_pdb): ] ), ) + u.trajectory.close() def test_fereader_negative_state(simulation_nc, hybrid_system_pdb): @@ -142,6 +146,7 @@ def test_fereader_negative_state(simulation_nc, hybrid_system_pdb): assert u.trajectory._state_id == 10 assert u.trajectory._replica_id is None + u.trajectory.close() def test_fereader_negative_replica(simulation_nc, hybrid_system_pdb): @@ -150,10 +155,11 @@ def test_fereader_negative_replica(simulation_nc, hybrid_system_pdb): assert u.trajectory._state_id is None assert u.trajectory._replica_id == 9 + u.trajectory.close() @pytest.mark.parametrize("rep_id, state_id", [[None, None], [1, 1]]) -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_fereader_replica_state_id_error(simulation_nc, hybrid_system_pdb, rep_id, state_id): with pytest.raises(ValueError, match="Specify one and only one"): _ = mda.Universe( @@ -178,3 +184,5 @@ def test_simulation_skipped_nc(simulation_skipped_nc, hybrid_system_skipped_pdb) assert np.all(u.atoms.positions > 0) with pytest.raises(mda.exceptions.NoDataError, match="This Timestep has no velocities"): u.atoms.velocities + + u.trajectory.close() diff --git a/src/openfe_analysis/tests/test_rmsd.py b/src/openfe_analysis/tests/test_rmsd.py index a108bbe..de9585b 100644 --- a/src/openfe_analysis/tests/test_rmsd.py +++ b/src/openfe_analysis/tests/test_rmsd.py @@ -6,7 +6,7 @@ from openfe_analysis.rmsd import gather_rms_data -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_gather_rms_data_regression(simulation_nc, hybrid_system_pdb): output = gather_rms_data( hybrid_system_pdb, @@ -43,7 +43,7 @@ def test_gather_rms_data_regression(simulation_nc, hybrid_system_pdb): ) -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_gather_rms_data_regression_skippednc(simulation_skipped_nc, hybrid_system_skipped_pdb): output = gather_rms_data( hybrid_system_skipped_pdb, diff --git a/src/openfe_analysis/tests/test_transformations.py b/src/openfe_analysis/tests/test_transformations.py index 96d4a0f..3244137 100644 --- a/src/openfe_analysis/tests/test_transformations.py +++ b/src/openfe_analysis/tests/test_transformations.py @@ -13,15 +13,17 @@ @pytest.fixture def universe(hybrid_system_pdb, simulation_nc): - return mda.Universe( + u = mda.Universe( hybrid_system_pdb, simulation_nc, format="MultiStateReporter", state_id=0, ) + yield u + u.trajectory.close() -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_minimiser(universe): prot = universe.select_atoms("protein and name CA") lig = universe.select_atoms("resname UNK") @@ -34,7 +36,7 @@ def test_minimiser(universe): assert d == pytest.approx(11.10, abs=0.01) -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_nojump(universe): # find frame where protein would teleport across boundary and check it prot = universe.select_atoms("protein and name CA") @@ -50,7 +52,7 @@ def test_nojump(universe): assert prot.center_of_mass() == pytest.approx(ref, abs=0.01) -@pytest.mark.flaky(reruns=3) +#@pytest.mark.flaky(reruns=3) def test_aligner(universe): # checks that rmsd is identical with/without center&super prot = universe.select_atoms("protein and name CA") diff --git a/src/openfe_analysis/tests/utils/test_multistate.py b/src/openfe_analysis/tests/utils/test_multistate.py index deb3281..69c5cb6 100644 --- a/src/openfe_analysis/tests/utils/test_multistate.py +++ b/src/openfe_analysis/tests/utils/test_multistate.py @@ -13,18 +13,25 @@ ) -@pytest.fixture(scope="module") +@pytest.fixture() def dataset(simulation_nc): - return nc.Dataset(simulation_nc) + ds = nc.Dataset(simulation_nc) + yield ds + ds.close() + + +@pytest.fixture() +def skipped_dataset(simulation_skipped_nc): + ds = nc.Dataset(simulation_skipped_nc) + yield ds + ds.close() -@pytest.mark.flaky(reruns=3) @pytest.mark.parametrize("state, frame, replica", [[0, 0, 0], [0, 1, 3], [0, -1, 7], [3, 100, 6]]) def test_state_to_replica(dataset, state, frame, replica): assert _state_to_replica(dataset, state, frame) == replica -@pytest.mark.flaky(reruns=3) def test_replica_positions_at_frame(dataset): pos = _replica_positions_at_frame(dataset, 1, -1) assert_allclose( @@ -69,6 +76,8 @@ def test_create_new_dataset(tmpdir): assert ds.variables["cell_angles"].get_dims()[1].name == "cell_angular" assert ds.variables["cell_angles"].dtype.name == "float64" + ds.close() + def test_get_unitcell(dataset): dims = _get_unitcell(dataset, 7, -1) @@ -79,9 +88,7 @@ def test_get_unitcell(dataset): def test_simulation_skipped_nc_no_positions_box_vectors_frame1( - simulation_skipped_nc, + skipped_dataset, ): - dataset = nc.Dataset(simulation_skipped_nc) - - assert _get_unitcell(dataset, 1, 1) is None - assert dataset.variables["positions"][1][0].mask.all() + assert _get_unitcell(skipped_dataset, 1, 1) is None + assert skipped_dataset.variables["positions"][1][0].mask.all()