diff --git a/.travis.yml b/.travis.yml index 90bc771..03cc830 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: python python: - '3.6' - '2.7' - - '3.4' - '3.5' branches: @@ -27,8 +26,6 @@ env: matrix: exclude: - - env: MDTRAJ="dev" - python: "3.4" - env: MDTRAJ="dev" python: "3.5" diff --git a/ci/conda-recipe/meta.yaml b/ci/conda-recipe/meta.yaml index d56c755..4d7323e 100644 --- a/ci/conda-recipe/meta.yaml +++ b/ci/conda-recipe/meta.yaml @@ -1,7 +1,7 @@ package: name: contact_map # add ".dev0" for unreleased versions - version: "0.3.0" + version: "0.3.1" source: path: ../../ diff --git a/contact_map/contact_map.py b/contact_map/contact_map.py index 005d938..c0b66a1 100644 --- a/contact_map/contact_map.py +++ b/contact_map/contact_map.py @@ -12,7 +12,6 @@ import mdtraj as md from .contact_count import ContactCount -from .plot_utils import ranged_colorbar from .py_2_3 import inspect_method_arguments # TODO: @@ -126,7 +125,7 @@ def from_dict(cls, dct): -------- to_dict """ - deserialize_set = lambda k: set(k) + deserialize_set = set deserialize_atom_to_residue_dct = lambda d: {int(k): d[k] for k in d} deserialization_helpers = { 'topology': cls._deserialize_topology, @@ -211,12 +210,23 @@ def from_json(cls, json_string): dct = json.loads(json_string) return cls.from_dict(dct) - def _check_compatibility(self, other): - assert self.cutoff == other.cutoff - assert self.topology == other.topology - assert self.query == other.query - assert self.haystack == other.haystack - assert self.n_neighbors_ignored == other.n_neighbors_ignored + def _check_compatibility(self, other, err=AssertionError): + compatibility_attrs = ['cutoff', 'topology', 'query', 'haystack', + 'n_neighbors_ignored'] + failed_attr = {} + for attr in compatibility_attrs: + self_val = getattr(self, attr) + other_val = getattr(other, attr) + if self_val != other_val: + failed_attr.update({attr: (self_val, other_val)}) + msg = "Incompatible ContactObjects:\n" + for (attr, vals) in failed_attr.items(): + msg += " {attr}: {self} != {other}\n".format( + attr=attr, self=str(vals[0]), other=str(vals[1]) + ) + if failed_attr: + raise err(msg) + return True def save_to_file(self, filename, mode="w"): """Save this object to the given file. diff --git a/contact_map/dask_runner.py b/contact_map/dask_runner.py index 5521a1c..8fbd777 100644 --- a/contact_map/dask_runner.py +++ b/contact_map/dask_runner.py @@ -84,16 +84,16 @@ def __init__(self, client, filename, query=None, haystack=None, self.filename = filename trajectory = md.load(filename, **kwargs) - self.frames = range(len(trajectory)) self.kwargs = kwargs - ContactObject.__init__(self, trajectory.topology, query, haystack, - cutoff, n_neighbors_ignored) + super(DaskContactFrequency, self).__init__( + trajectory, query, haystack, cutoff, n_neighbors_ignored + ) - freq = dask_run(trajectory, client, self.run_info) - self._n_frames = freq.n_frames - self._atom_contacts = freq._atom_contacts - self._residue_contacts = freq._residue_contacts + def _build_contact_map(self, trajectory): + freq = dask_run(trajectory, self.client, self.run_info) + self._frames = freq.n_frames + return (freq._atom_contacts, freq._residue_contacts) @property def parameters(self): diff --git a/contact_map/tests/test_contact_map.py b/contact_map/tests/test_contact_map.py index 99af6cd..3a3eece 100644 --- a/contact_map/tests/test_contact_map.py +++ b/contact_map/tests/test_contact_map.py @@ -1,6 +1,5 @@ import os import collections -import json import mdtraj as md # pylint: disable=wildcard-import, missing-docstring, protected-access @@ -133,7 +132,6 @@ def test_counters(self, idx): def test_to_dict(self, idx): m = self.maps[idx] - json_topol = json.dumps(pdb_topology_dict()) dct = m.to_dict() # NOTE: topology only tested in a cycle; JSON order not guaranteed assert dct['cutoff'] == 0.075 @@ -279,6 +277,35 @@ def test_counters(self): } assert residue_contacts.counter == expected_residue_contacts + def test_check_compatibility_true(self): + map2 = ContactFrequency(trajectory=traj[0:2], + cutoff=0.075, + n_neighbors_ignored=0) + assert self.map._check_compatibility(map2) == True + + @pytest.mark.parametrize("diff", [ + {'trajectory': traj.atom_slice([0, 1, 2, 3])}, + {'cutoff': 0.45}, + {'n_neighbors_ignored': 2}, + {'query': [1, 2, 3, 4]}, + {'haystack': [1, 2, 3, 4]} + ]) + def test_check_compatibility_assertion_error(self, diff): + params = {'trajectory': traj[0:2], + 'cutoff': 0.075, + 'n_neighbors_ignored': 0} + params.update(diff) + map2 = ContactFrequency(**params) + with pytest.raises(AssertionError): + self.map._check_compatibility(map2) + + def test_check_compatibility_runtime_error(self): + map2 = ContactFrequency(trajectory=traj, + cutoff=0.45, + n_neighbors_ignored=2) + with pytest.raises(RuntimeError): + self.map._check_compatibility(map2, err=RuntimeError) + @pytest.mark.parametrize("intermediate", ["dict", "json"]) def test_serialization_cycle(self, intermediate): serializer, deserializer = { diff --git a/contact_map/tests/test_dask_runner.py b/contact_map/tests/test_dask_runner.py index 7f804be..d72cb18 100644 --- a/contact_map/tests/test_dask_runner.py +++ b/contact_map/tests/test_dask_runner.py @@ -9,7 +9,7 @@ class TestDaskContactFrequency(object): def test_dask_integration(self): # this is an integration test to check that dask works - dask = pytest.importorskip('dask') + dask = pytest.importorskip('dask') # pylint: disable=W0612 distributed = pytest.importorskip('dask.distributed') client = distributed.Client() diff --git a/contact_map/tests/test_frequency_task.py b/contact_map/tests/test_frequency_task.py index 6a79038..57eab69 100644 --- a/contact_map/tests/test_frequency_task.py +++ b/contact_map/tests/test_frequency_task.py @@ -1,5 +1,6 @@ -import os -import collections +# pylint: disable=wildcard-import, missing-docstring, protected-access +# pylint: disable=attribute-defined-outside-init, invalid-name, no-self-use +# pylint: disable=wrong-import-order, unused-wildcard-import from .utils import * from .test_contact_map import traj diff --git a/contact_map/tests/utils.py b/contact_map/tests/utils.py index b600d4e..926d9bf 100644 --- a/contact_map/tests/utils.py +++ b/contact_map/tests/utils.py @@ -1,7 +1,9 @@ import os -import numpy as np from pkg_resources import resource_filename +# pylint: disable=unused-import + +import numpy as np from numpy.testing import assert_array_equal, assert_allclose import pytest diff --git a/setup.py b/setup.py index a149a9e..cafee03 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ ####################### USER SETUP AREA ################################# # * VERSION: base version (do not include .dev0, etc -- that's automatic) # * IS_RELEASE: whether this is a release -VERSION = "0.3.0" +VERSION = "0.3.1" IS_RELEASE = True DEV_NUM = 0 # always 0: we don't do public (pypi) .dev releases