pyjess 0.7.0__cp38-abi3-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyjess might be problematic. Click here for more details.
- pyjess/.gitignore +2 -0
- pyjess/CMakeLists.txt +1 -0
- pyjess/__init__.py +21 -0
- pyjess/__main__.py +4 -0
- pyjess/_jess.abi3.so +0 -0
- pyjess/_jess.pyi +268 -0
- pyjess/_jess.pyx +2371 -0
- pyjess/cli.py +281 -0
- pyjess/py.typed +0 -0
- pyjess/tests/__init__.py +20 -0
- pyjess/tests/data/1.3.3.tpl +23 -0
- pyjess/tests/data/1AMY+1.3.3.txt +1872 -0
- pyjess/tests/data/1AMY.cif +6259 -0
- pyjess/tests/data/1AMY.pdb +3941 -0
- pyjess/tests/data/1sur.qry +26 -0
- pyjess/tests/data/4.1.2.tpl +23 -0
- pyjess/tests/data/5ayx.EF.pdb +63 -0
- pyjess/tests/data/__init__.py +0 -0
- pyjess/tests/data/pdb1lnb.pdb +3334 -0
- pyjess/tests/data/template_01.qry +11 -0
- pyjess/tests/data/template_02.qry +11 -0
- pyjess/tests/test_atom.py +111 -0
- pyjess/tests/test_doctest.py +78 -0
- pyjess/tests/test_hit.py +57 -0
- pyjess/tests/test_jess.py +374 -0
- pyjess/tests/test_molecule.py +287 -0
- pyjess/tests/test_template.py +126 -0
- pyjess/tests/test_template_atom.py +92 -0
- pyjess/tests/utils.py +7 -0
- pyjess-0.7.0.dist-info/METADATA +282 -0
- pyjess-0.7.0.dist-info/RECORD +34 -0
- pyjess-0.7.0.dist-info/WHEEL +5 -0
- pyjess-0.7.0.dist-info/entry_points.txt +3 -0
- pyjess-0.7.0.dist-info/licenses/COPYING +21 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ATOM 0 ND1 HIS E 142 4.191 -2.584 4.209
|
|
2
|
+
ATOM 0 NE2 HIS E 142 3.847 -2.332 2.058
|
|
3
|
+
ATOM 0 OE1 GLU E 143 0.491 -4.480 -0.456
|
|
4
|
+
ATOM 0 OE2 GLU E 143 1.864 -5.931 0.301
|
|
5
|
+
ATOM 0 CG HIS E 146 0.000 0.000 0.000
|
|
6
|
+
ATOM 0 ND1 HIS E 146 0.837 1.123 0.000
|
|
7
|
+
ATOM 0 CD2 HIS E 146 0.809 -1.085 0.000
|
|
8
|
+
ATOM 0 CE1 HIS E 146 2.102 0.717 -0.028
|
|
9
|
+
ATOM 0 NE2 HIS E 146 2.112 -0.611 -0.015
|
|
10
|
+
ATOM 0 OE1 GLU E 166 5.568 -0.214 0.181
|
|
11
|
+
ATOM 0 OE2 GLU E 166 5.790 -0.332 0.398
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ATOM 0 NZ LYS A1030 1.431 -9.717 -1.722
|
|
2
|
+
ATOM 0 CG ASP A1132 0.000 0.000 0.000
|
|
3
|
+
ATOM 0 OD1 ASP A1132 0.595 1.085 0.000
|
|
4
|
+
ATOM 0 OD2 ASP A1132 0.609 -1.111 0.000
|
|
5
|
+
ATOM 1 NE ARG A1136 3.953 0.597 -1.721 K
|
|
6
|
+
ATOM 0 CG ASN A1137 0.736 -1.869 -4.261
|
|
7
|
+
ATOM 0 OD1 ASN A1137 1.760 -2.435 -4.344
|
|
8
|
+
ATOM 0 ND2 ASN A1137 0.264 -1.477 -3.134
|
|
9
|
+
ATOM 0 CG ASP A1150 -0.010 -5.408 -2.070
|
|
10
|
+
ATOM 0 OD1 ASP A1150 -0.587 -5.769 -1.153
|
|
11
|
+
ATOM 0 OD2 ASP A1150 1.085 -5.212 -2.011
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import unittest
|
|
3
|
+
import pickle
|
|
4
|
+
|
|
5
|
+
from .._jess import Atom
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAtom(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
def _create_atom(self, **kwargs):
|
|
11
|
+
default = dict(serial=1, name='N', altloc=' ', residue_name='GLN', chain_id='A', residue_number=3, x=8.171, y=-51.403, z=42.886, segment='', insertion_code=' ', occupancy=1.0, temperature_factor=55.63, charge=0, element='N')
|
|
12
|
+
default.update(kwargs)
|
|
13
|
+
return Atom(**default)
|
|
14
|
+
|
|
15
|
+
def test_load(self):
|
|
16
|
+
atom = Atom.loads("ATOM 39 CA PRO A 469 -14.948 2.091 10.228 1.00 27.71 C")
|
|
17
|
+
self.assertEqual(atom.serial, 39)
|
|
18
|
+
self.assertEqual(atom.name, 'CA')
|
|
19
|
+
self.assertEqual(atom.residue_name, 'PRO')
|
|
20
|
+
self.assertEqual(atom.chain_id, 'A')
|
|
21
|
+
self.assertEqual(atom.residue_number, 469)
|
|
22
|
+
self.assertAlmostEqual(atom.x, -14.948, places=3)
|
|
23
|
+
self.assertAlmostEqual(atom.y, 2.091, places=3)
|
|
24
|
+
self.assertAlmostEqual(atom.z, 10.228, places=3)
|
|
25
|
+
self.assertAlmostEqual(atom.occupancy, 1.00, places=2)
|
|
26
|
+
self.assertAlmostEqual(atom.temperature_factor, 27.71, places=2)
|
|
27
|
+
self.assertEqual(atom.segment, '')
|
|
28
|
+
self.assertEqual(atom.element, 'C')
|
|
29
|
+
self.assertEqual(atom.charge, 0)
|
|
30
|
+
|
|
31
|
+
def test_init_consistency(self):
|
|
32
|
+
loaded = Atom.loads("ATOM 39 CA PRO A 469 -14.948 2.091 10.228 1.00 27.71 C")
|
|
33
|
+
created = Atom(
|
|
34
|
+
serial=loaded.serial,
|
|
35
|
+
name=loaded.name,
|
|
36
|
+
residue_name=loaded.residue_name,
|
|
37
|
+
chain_id=loaded.chain_id,
|
|
38
|
+
altloc=loaded.altloc,
|
|
39
|
+
insertion_code=loaded.insertion_code,
|
|
40
|
+
residue_number=loaded.residue_number,
|
|
41
|
+
x=loaded.x,
|
|
42
|
+
y=loaded.y,
|
|
43
|
+
z=loaded.z,
|
|
44
|
+
occupancy=loaded.occupancy,
|
|
45
|
+
temperature_factor=loaded.temperature_factor,
|
|
46
|
+
element=loaded.element,
|
|
47
|
+
)
|
|
48
|
+
self.assertEqual(loaded, created)
|
|
49
|
+
|
|
50
|
+
def test_init_invalid_chain_id(self):
|
|
51
|
+
self.assertRaises(ValueError, self._create_atom, chain_id="too long")
|
|
52
|
+
|
|
53
|
+
def test_init_invalid_name(self):
|
|
54
|
+
self.assertRaises(ValueError, self._create_atom, name="too long")
|
|
55
|
+
|
|
56
|
+
def test_init_invalid_residue_name(self):
|
|
57
|
+
self.assertRaises(ValueError, self._create_atom, residue_name="too long")
|
|
58
|
+
|
|
59
|
+
def test_hash(self):
|
|
60
|
+
a1 = self._create_atom()
|
|
61
|
+
a2 = self._create_atom()
|
|
62
|
+
self.assertEqual(hash(a1), hash(a2))
|
|
63
|
+
self.assertIsNot(a1, a2)
|
|
64
|
+
a3 = self._create_atom(x=1.0)
|
|
65
|
+
self.assertNotEqual(hash(a1), hash(a3))
|
|
66
|
+
|
|
67
|
+
def test_eq(self):
|
|
68
|
+
a1 = self._create_atom()
|
|
69
|
+
a2 = self._create_atom()
|
|
70
|
+
self.assertEqual(a1, a2)
|
|
71
|
+
self.assertIsNot(a1, a2)
|
|
72
|
+
a3 = self._create_atom(x=1.0)
|
|
73
|
+
self.assertNotEqual(a1, a3)
|
|
74
|
+
|
|
75
|
+
def test_repr_roundtrip(self):
|
|
76
|
+
atom = self._create_atom()
|
|
77
|
+
copy = eval(repr(atom))
|
|
78
|
+
self.assertEqual(atom.serial, copy.serial)
|
|
79
|
+
self.assertEqual(atom.altloc, copy.altloc)
|
|
80
|
+
self.assertEqual(atom.name, copy.name)
|
|
81
|
+
self.assertEqual(atom.residue_name, copy.residue_name)
|
|
82
|
+
self.assertEqual(atom.residue_number, copy.residue_number)
|
|
83
|
+
self.assertEqual(atom.element, copy.element)
|
|
84
|
+
self.assertEqual(atom.insertion_code, copy.insertion_code)
|
|
85
|
+
self.assertEqual(atom.chain_id, copy.chain_id)
|
|
86
|
+
self.assertEqual(atom.occupancy, copy.occupancy)
|
|
87
|
+
self.assertEqual(atom.temperature_factor, copy.temperature_factor)
|
|
88
|
+
self.assertEqual(atom.charge, copy.charge)
|
|
89
|
+
self.assertEqual(atom.x, copy.x)
|
|
90
|
+
self.assertEqual(atom.y, copy.y)
|
|
91
|
+
self.assertEqual(atom.z, copy.z)
|
|
92
|
+
self.assertEqual(atom, copy)
|
|
93
|
+
|
|
94
|
+
def test_pickle_roundtrip(self):
|
|
95
|
+
atom = self._create_atom()
|
|
96
|
+
copy = pickle.loads(pickle.dumps(atom))
|
|
97
|
+
self.assertEqual(atom.serial, copy.serial)
|
|
98
|
+
self.assertEqual(atom.altloc, copy.altloc)
|
|
99
|
+
self.assertEqual(atom.name, copy.name)
|
|
100
|
+
self.assertEqual(atom.residue_name, copy.residue_name)
|
|
101
|
+
self.assertEqual(atom.residue_number, copy.residue_number)
|
|
102
|
+
self.assertEqual(atom.element, copy.element)
|
|
103
|
+
self.assertEqual(atom.insertion_code, copy.insertion_code)
|
|
104
|
+
self.assertEqual(atom.chain_id, copy.chain_id)
|
|
105
|
+
self.assertEqual(atom.occupancy, copy.occupancy)
|
|
106
|
+
self.assertEqual(atom.temperature_factor, copy.temperature_factor)
|
|
107
|
+
self.assertEqual(atom.charge, copy.charge)
|
|
108
|
+
self.assertEqual(atom.x, copy.x)
|
|
109
|
+
self.assertEqual(atom.y, copy.y)
|
|
110
|
+
self.assertEqual(atom.z, copy.z)
|
|
111
|
+
self.assertEqual(atom, copy)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
"""Test doctest contained tests in every file of the module.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import configparser
|
|
6
|
+
import doctest
|
|
7
|
+
import importlib
|
|
8
|
+
import json
|
|
9
|
+
import gzip
|
|
10
|
+
import os
|
|
11
|
+
import pkgutil
|
|
12
|
+
import re
|
|
13
|
+
import shutil
|
|
14
|
+
import sys
|
|
15
|
+
import types
|
|
16
|
+
import warnings
|
|
17
|
+
from unittest import mock
|
|
18
|
+
|
|
19
|
+
import pyjess
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _load_tests_from_module(tests, module, globs, setUp=None, tearDown=None):
|
|
23
|
+
"""Load tests from module, iterating through submodules."""
|
|
24
|
+
for attr in (getattr(module, x) for x in dir(module) if not x.startswith("_")):
|
|
25
|
+
if isinstance(attr, types.ModuleType):
|
|
26
|
+
suite = doctest.DocTestSuite(
|
|
27
|
+
attr,
|
|
28
|
+
globs,
|
|
29
|
+
setUp=setUp,
|
|
30
|
+
tearDown=tearDown,
|
|
31
|
+
optionflags=+doctest.ELLIPSIS,
|
|
32
|
+
)
|
|
33
|
+
tests.addTests(suite)
|
|
34
|
+
return tests
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_tests(loader, tests, ignore):
|
|
38
|
+
"""`load_test` function used by unittest to find the doctests."""
|
|
39
|
+
_current_cwd = os.getcwd()
|
|
40
|
+
|
|
41
|
+
def setUp(self):
|
|
42
|
+
warnings.simplefilter("ignore")
|
|
43
|
+
os.chdir(os.path.realpath(os.path.join(__file__, os.path.pardir, "data")))
|
|
44
|
+
|
|
45
|
+
def tearDown(self):
|
|
46
|
+
os.chdir(_current_cwd)
|
|
47
|
+
warnings.simplefilter(warnings.defaultaction)
|
|
48
|
+
|
|
49
|
+
# doctests are not compatible with `green`, so we may want to bail out
|
|
50
|
+
# early if `green` is running the tests
|
|
51
|
+
if sys.argv[0].endswith("green"):
|
|
52
|
+
return tests
|
|
53
|
+
|
|
54
|
+
# recursively traverse all library submodules and load tests from them
|
|
55
|
+
packages = [None, pyjess]
|
|
56
|
+
for pkg in iter(packages.pop, None):
|
|
57
|
+
for (_, subpkgname, subispkg) in pkgutil.walk_packages(pkg.__path__):
|
|
58
|
+
# do not import __main__ module to avoid side effects!
|
|
59
|
+
if subpkgname == "__main__" or subpkgname.startswith("tests") or subpkgname.startswith("cli"):
|
|
60
|
+
continue
|
|
61
|
+
# import the submodule and add it to the tests
|
|
62
|
+
module = importlib.import_module(".".join([pkg.__name__, subpkgname]))
|
|
63
|
+
globs = dict(pyjess=pyjess, **module.__dict__)
|
|
64
|
+
tests.addTests(
|
|
65
|
+
doctest.DocTestSuite(
|
|
66
|
+
module,
|
|
67
|
+
globs=globs,
|
|
68
|
+
setUp=setUp,
|
|
69
|
+
tearDown=tearDown,
|
|
70
|
+
optionflags=+doctest.ELLIPSIS,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
# if the submodule is a package, we need to process its submodules
|
|
74
|
+
# as well, so we add it to the package queue
|
|
75
|
+
if subispkg and subpkgname != "tests":
|
|
76
|
+
packages.append(module)
|
|
77
|
+
|
|
78
|
+
return tests
|
pyjess/tests/test_hit.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import unittest
|
|
3
|
+
import sys
|
|
4
|
+
import pickle
|
|
5
|
+
import textwrap
|
|
6
|
+
|
|
7
|
+
from .._jess import Template, Molecule, Jess
|
|
8
|
+
from .utils import files
|
|
9
|
+
from . import data
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestHit(unittest.TestCase):
|
|
13
|
+
|
|
14
|
+
maxDiff = None
|
|
15
|
+
|
|
16
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
17
|
+
@classmethod
|
|
18
|
+
def setUpClass(cls):
|
|
19
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
20
|
+
template = Template.load(f, id="T1")
|
|
21
|
+
jess = Jess([template])
|
|
22
|
+
with files(data).joinpath("pdb1lnb.pdb").open() as f:
|
|
23
|
+
molecule = Molecule.load(f)
|
|
24
|
+
|
|
25
|
+
cls.hit = next(jess.query(molecule, 1, 2, 2))
|
|
26
|
+
|
|
27
|
+
def test_pickle(self):
|
|
28
|
+
hit = pickle.loads(pickle.dumps(self.hit))
|
|
29
|
+
self.assertIsNot(self.hit, hit)
|
|
30
|
+
self.assertEqual(self.hit.rmsd, hit.rmsd)
|
|
31
|
+
self.assertEqual(self.hit.determinant, hit.determinant)
|
|
32
|
+
self.assertEqual(self.hit.evalue, hit.evalue)
|
|
33
|
+
self.assertEqual(self.hit.template, hit.template)
|
|
34
|
+
self.assertListEqual(self.hit.atoms(transform=True), hit.atoms(transform=True))
|
|
35
|
+
self.assertListEqual(self.hit.atoms(transform=False), hit.atoms(transform=False))
|
|
36
|
+
self.assertEqual(self.hit.molecule(transform=False), hit.molecule(transform=False))
|
|
37
|
+
|
|
38
|
+
def test_dumps(self):
|
|
39
|
+
expected = textwrap.dedent(
|
|
40
|
+
"""
|
|
41
|
+
REMARK 1LNB 0.555 T1 Det= 1.0 log(E)~ -2.04
|
|
42
|
+
ATOM 1112 ND1 HIS E 142 4.157 -2.574 4.091 1.00 10.22
|
|
43
|
+
ATOM 1115 NE2 HIS E 142 3.805 -2.316 1.890 1.00 16.00
|
|
44
|
+
ATOM 1123 OE1 GLU E 143 0.480 -4.544 -0.363 1.00 14.72
|
|
45
|
+
ATOM 1124 OE2 GLU E 143 1.870 -6.097 0.337 1.00 22.48
|
|
46
|
+
ATOM 1145 CG HIS E 146 0.031 0.017 0.019 1.00 12.45
|
|
47
|
+
ATOM 1146 ND1 HIS E 146 0.823 1.160 0.000 1.00 15.79
|
|
48
|
+
ATOM 1147 CD2 HIS E 146 0.878 -1.064 0.006 1.00 20.85
|
|
49
|
+
ATOM 1148 CE1 HIS E 146 2.115 0.777 -0.013 1.00 13.50
|
|
50
|
+
ATOM 1149 NE2 HIS E 146 2.181 -0.553 -0.032 1.00 12.44
|
|
51
|
+
ATOM 1298 OE1 GLU E 166 6.432 -0.605 1.056 1.00 16.03
|
|
52
|
+
ATOM 1299 OE2 GLU E 166 4.839 0.070 -0.343 1.00 19.31
|
|
53
|
+
ENDMDL
|
|
54
|
+
"""
|
|
55
|
+
).strip()
|
|
56
|
+
actual = self.hit.dumps().strip()
|
|
57
|
+
self.assertMultiLineEqual(actual, expected)
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import unittest
|
|
3
|
+
import sys
|
|
4
|
+
import pickle
|
|
5
|
+
|
|
6
|
+
from .._jess import Template, Molecule, Jess
|
|
7
|
+
from .utils import files
|
|
8
|
+
from . import data
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestJess(unittest.TestCase):
|
|
12
|
+
|
|
13
|
+
def test_init_empty(self):
|
|
14
|
+
jess = Jess()
|
|
15
|
+
self.assertEqual(len(jess), 0)
|
|
16
|
+
self.assertFalse(bool(jess))
|
|
17
|
+
|
|
18
|
+
def test_query_empty(self):
|
|
19
|
+
mol = Molecule()
|
|
20
|
+
jess = Jess()
|
|
21
|
+
hits = jess.query(mol, 2, 2, 4)
|
|
22
|
+
self.assertRaises(StopIteration, next, hits)
|
|
23
|
+
|
|
24
|
+
def test_hash_empty(self):
|
|
25
|
+
j1 = Jess()
|
|
26
|
+
j2 = Jess()
|
|
27
|
+
self.assertEqual(j1, j2)
|
|
28
|
+
self.assertEqual(hash(j1), hash(j2))
|
|
29
|
+
self.assertIsNot(j1, j2)
|
|
30
|
+
|
|
31
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
32
|
+
def test_copy(self):
|
|
33
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
34
|
+
template1 = Template.load(f)
|
|
35
|
+
with files(data).joinpath("template_02.qry").open() as f:
|
|
36
|
+
template2 = Template.load(f)
|
|
37
|
+
jess = Jess([template1, template2])
|
|
38
|
+
copy = jess.copy()
|
|
39
|
+
self.assertEqual(jess, copy)
|
|
40
|
+
|
|
41
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
42
|
+
def test_hash(self):
|
|
43
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
44
|
+
template1 = Template.load(f)
|
|
45
|
+
with files(data).joinpath("template_02.qry").open() as f:
|
|
46
|
+
template2 = Template.load(f)
|
|
47
|
+
j1 = Jess([template1, template2])
|
|
48
|
+
j2 = Jess([template1, template2])
|
|
49
|
+
self.assertEqual(hash(j1), hash(j2))
|
|
50
|
+
self.assertIsNot(j1, j2)
|
|
51
|
+
j3 = Jess([template1])
|
|
52
|
+
self.assertNotEqual(hash(j1), hash(j3))
|
|
53
|
+
|
|
54
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
55
|
+
def test_eq(self):
|
|
56
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
57
|
+
template1 = Template.load(f)
|
|
58
|
+
with files(data).joinpath("template_02.qry").open() as f:
|
|
59
|
+
template2 = Template.load(f)
|
|
60
|
+
j1 = Jess([template1, template2])
|
|
61
|
+
j2 = Jess([template1, template2])
|
|
62
|
+
self.assertEqual(j1, j2)
|
|
63
|
+
self.assertIsNot(j1, j2)
|
|
64
|
+
j3 = Jess([template1])
|
|
65
|
+
self.assertNotEqual(j1, j3)
|
|
66
|
+
|
|
67
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
68
|
+
def test_pickle_roundtrip(self):
|
|
69
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
70
|
+
template1 = Template.load(f)
|
|
71
|
+
with files(data).joinpath("template_02.qry").open() as f:
|
|
72
|
+
template2 = Template.load(f)
|
|
73
|
+
jess = Jess([template1, template2])
|
|
74
|
+
copy = pickle.loads(pickle.dumps(jess))
|
|
75
|
+
self.assertEqual(jess, copy)
|
|
76
|
+
|
|
77
|
+
@unittest.skipUnless(sys.implementation.name == "cpython", "only available on CPython")
|
|
78
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
79
|
+
def test_sizeof(self):
|
|
80
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
81
|
+
template = Template.load(f)
|
|
82
|
+
jess = Jess([template])
|
|
83
|
+
self.assertGreater(sys.getsizeof(jess), 0)
|
|
84
|
+
|
|
85
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
86
|
+
def test_getitem(self):
|
|
87
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
88
|
+
template = Template.load(f)
|
|
89
|
+
jess = Jess([template])
|
|
90
|
+
|
|
91
|
+
self.assertEqual(jess[0], template)
|
|
92
|
+
self.assertEqual(len(jess[:1]), 1)
|
|
93
|
+
self.assertEqual(len(jess[1:]), 0)
|
|
94
|
+
|
|
95
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
96
|
+
def test_multiple_query_split(self):
|
|
97
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
98
|
+
template1 = Template.load(f)
|
|
99
|
+
with files(data).joinpath("template_02.qry").open() as f:
|
|
100
|
+
template2 = Template.load(f)
|
|
101
|
+
j0 = Jess([template1, template2])
|
|
102
|
+
j1 = Jess([template1])
|
|
103
|
+
j2 = Jess([template2])
|
|
104
|
+
|
|
105
|
+
with files(data).joinpath("1AMY.pdb").open() as f:
|
|
106
|
+
molecule = Molecule.load(f)
|
|
107
|
+
|
|
108
|
+
h0 = list(j0.query(molecule, 2, 5, 5))
|
|
109
|
+
h1 = list(j1.query(molecule, 2, 5, 5))
|
|
110
|
+
h2 = list(j2.query(molecule, 2, 5, 5))
|
|
111
|
+
|
|
112
|
+
self.assertEqual(len(h0), len(h1) + len(h2))
|
|
113
|
+
for hit0, hit1 in zip(h0, (*h1, *h2)):
|
|
114
|
+
self.assertEqual(hit0.atoms(), hit1.atoms())
|
|
115
|
+
self.assertEqual(hit0.evalue, hit1.evalue)
|
|
116
|
+
|
|
117
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
118
|
+
def test_query_template_subclass(self):
|
|
119
|
+
|
|
120
|
+
class MyTemplate(Template):
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
124
|
+
template = MyTemplate.load(f)
|
|
125
|
+
jess = Jess([template])
|
|
126
|
+
with files(data).joinpath("pdb1lnb.pdb").open() as f:
|
|
127
|
+
molecule = Molecule.load(f)
|
|
128
|
+
|
|
129
|
+
self.assertEqual(jess[0], template)
|
|
130
|
+
self.assertIsInstance(jess[0], MyTemplate)
|
|
131
|
+
hits = list(jess.query(molecule, 1, 2, 2))
|
|
132
|
+
self.assertIsInstance(hits[0].template, MyTemplate)
|
|
133
|
+
|
|
134
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
135
|
+
def test_query_max_candidates(self):
|
|
136
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
137
|
+
template = Template.load(f)
|
|
138
|
+
jess = Jess([template])
|
|
139
|
+
with files(data).joinpath("pdb1lnb.pdb").open() as f:
|
|
140
|
+
molecule = Molecule.load(f)
|
|
141
|
+
|
|
142
|
+
hits = list(jess.query(molecule, 2, 5, 5))
|
|
143
|
+
self.assertEqual(len(hits), 3)
|
|
144
|
+
|
|
145
|
+
hits = list(jess.query(molecule, 2, 5, 5, max_candidates=3))
|
|
146
|
+
self.assertEqual(len(hits), 3)
|
|
147
|
+
|
|
148
|
+
hits = list(jess.query(molecule, 2, 5, 5, max_candidates=2))
|
|
149
|
+
self.assertEqual(len(hits), 2)
|
|
150
|
+
|
|
151
|
+
hits = list(jess.query(molecule, 2, 5, 5, max_candidates=1))
|
|
152
|
+
self.assertEqual(len(hits), 1)
|
|
153
|
+
|
|
154
|
+
with self.assertRaises(ValueError):
|
|
155
|
+
hits = list(jess.query(molecule, 2, 5, 5, max_candidates=-1))
|
|
156
|
+
|
|
157
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
158
|
+
def test_query(self):
|
|
159
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
160
|
+
template = Template.load(f)
|
|
161
|
+
jess = Jess([template])
|
|
162
|
+
with files(data).joinpath("pdb1lnb.pdb").open() as f:
|
|
163
|
+
molecule = Molecule.load(f)
|
|
164
|
+
|
|
165
|
+
hits = list(jess.query(molecule, 1, 2, 2))
|
|
166
|
+
self.assertEqual(len(hits), 1)
|
|
167
|
+
self.assertIs(hits[0].template, template)
|
|
168
|
+
self.assertAlmostEqual(hits[0].rmsd, 0.555, places=3)
|
|
169
|
+
self.assertAlmostEqual(hits[0].determinant, 1.0, places=3)
|
|
170
|
+
self.assertAlmostEqual(hits[0].log_evalue, -2.04, places=1)
|
|
171
|
+
self.assertAlmostEqual(hits[0].evalue, math.exp(-2.04), places=1)
|
|
172
|
+
|
|
173
|
+
hits = list(jess.query(molecule, 2, 5, 3))
|
|
174
|
+
self.assertEqual(len(hits), 2)
|
|
175
|
+
self.assertIs(hits[0].template, template)
|
|
176
|
+
self.assertAlmostEqual(hits[0].rmsd, 0.555, places=3)
|
|
177
|
+
self.assertAlmostEqual(hits[0].determinant, 1.0, places=3)
|
|
178
|
+
self.assertAlmostEqual(hits[0].log_evalue, -2.04, places=1)
|
|
179
|
+
self.assertAlmostEqual(hits[0].evalue, math.exp(-2.04), places=1)
|
|
180
|
+
self.assertIs(hits[1].template, template)
|
|
181
|
+
self.assertAlmostEqual(hits[1].rmsd, 1.440, places=3)
|
|
182
|
+
self.assertAlmostEqual(hits[1].determinant, 1.0, places=3)
|
|
183
|
+
self.assertAlmostEqual(hits[1].log_evalue, 0.17, places=1)
|
|
184
|
+
self.assertAlmostEqual(hits[1].evalue, math.exp(0.17), places=1)
|
|
185
|
+
|
|
186
|
+
hits = list(jess.query(molecule, 2, 5, 5))
|
|
187
|
+
self.assertEqual(len(hits), 3)
|
|
188
|
+
self.assertIs(hits[0].template, template)
|
|
189
|
+
self.assertAlmostEqual(hits[0].rmsd, 0.555, places=3)
|
|
190
|
+
self.assertAlmostEqual(hits[0].determinant, 1.0, places=3)
|
|
191
|
+
self.assertAlmostEqual(hits[0].log_evalue, -2.04, places=1)
|
|
192
|
+
self.assertAlmostEqual(hits[0].evalue, math.exp(-2.04), places=1)
|
|
193
|
+
self.assertIs(hits[1].template, template)
|
|
194
|
+
self.assertAlmostEqual(hits[1].rmsd, 1.440, places=3)
|
|
195
|
+
self.assertAlmostEqual(hits[1].determinant, 1.0, places=3)
|
|
196
|
+
self.assertAlmostEqual(hits[1].log_evalue, 0.17, places=1)
|
|
197
|
+
self.assertAlmostEqual(hits[1].evalue, math.exp(0.17), places=1)
|
|
198
|
+
self.assertIs(hits[2].template, template)
|
|
199
|
+
self.assertAlmostEqual(hits[2].rmsd, 1.644, places=3)
|
|
200
|
+
self.assertAlmostEqual(hits[2].determinant, 1.0, places=3)
|
|
201
|
+
self.assertAlmostEqual(hits[2].log_evalue, 0.68, places=1)
|
|
202
|
+
self.assertAlmostEqual(hits[2].evalue, math.exp(0.68), places=1)
|
|
203
|
+
|
|
204
|
+
hits = list(jess.query(molecule.conserved(10.0), 1, 2, 2))
|
|
205
|
+
self.assertEqual(len(hits), 1)
|
|
206
|
+
self.assertIs(hits[0].template, template)
|
|
207
|
+
self.assertAlmostEqual(hits[0].rmsd, 0.555, places=3)
|
|
208
|
+
self.assertAlmostEqual(hits[0].determinant, 1.0, places=3)
|
|
209
|
+
self.assertAlmostEqual(hits[0].log_evalue, -2.10, places=1)
|
|
210
|
+
self.assertAlmostEqual(hits[0].evalue, math.exp(-2.10), places=1)
|
|
211
|
+
|
|
212
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
213
|
+
def test_query_best_match(self):
|
|
214
|
+
with files(data).joinpath("template_01.qry").open() as f:
|
|
215
|
+
template = Template.load(f)
|
|
216
|
+
jess = Jess([template, template, template])
|
|
217
|
+
with files(data).joinpath("pdb1lnb.pdb").open() as f:
|
|
218
|
+
molecule = Molecule.load(f)
|
|
219
|
+
|
|
220
|
+
hits = list(jess.query(molecule, 2, 5, 5, best_match=True))
|
|
221
|
+
self.assertEqual(len(hits), 3)
|
|
222
|
+
for hit in hits:
|
|
223
|
+
self.assertIs(hit.template, template)
|
|
224
|
+
self.assertAlmostEqual(hit.rmsd, 0.555, places=3)
|
|
225
|
+
self.assertAlmostEqual(hit.determinant, 1.0, places=3)
|
|
226
|
+
self.assertAlmostEqual(hit.log_evalue, -2.04, places=1)
|
|
227
|
+
|
|
228
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
229
|
+
def test_mcsa_query_no_reorder(self):
|
|
230
|
+
with files(data).joinpath("1.3.3.tpl").open() as f:
|
|
231
|
+
template = Template.load(f)
|
|
232
|
+
jess = Jess([template])
|
|
233
|
+
with files(data).joinpath("1AMY.pdb").open() as f:
|
|
234
|
+
molecule = Molecule.load(f)
|
|
235
|
+
with files(data).joinpath("1AMY+1.3.3.txt").open() as f:
|
|
236
|
+
results = list(filter(None, f.read().split("REMARK")))
|
|
237
|
+
|
|
238
|
+
hits = list(jess.query(molecule, 2, 4, 4, reorder=False))
|
|
239
|
+
self.assertEqual(len(hits), len(results))
|
|
240
|
+
for hit, block in zip(hits, results):
|
|
241
|
+
self.assertIs(hit.template, template)
|
|
242
|
+
|
|
243
|
+
lines = block.strip().splitlines()
|
|
244
|
+
query_id, rmsd, template_id, _, determinant, _, logE = lines[0].split()
|
|
245
|
+
self.assertEqual(query_id, "1AMY")
|
|
246
|
+
self.assertAlmostEqual(float(rmsd), hit.rmsd, places=3)
|
|
247
|
+
self.assertAlmostEqual(float(determinant), hit.determinant, places=1)
|
|
248
|
+
self.assertAlmostEqual(float(logE), hit.log_evalue, places=1)
|
|
249
|
+
|
|
250
|
+
atom_lines = lines[1:-1]
|
|
251
|
+
atoms = hit.atoms()
|
|
252
|
+
self.assertEqual(len(atoms), len(atom_lines))
|
|
253
|
+
for atom, atom_line in zip(atoms, atom_lines):
|
|
254
|
+
self.assertEqual(atom.serial, int(atom_line[7:12]))
|
|
255
|
+
self.assertEqual(atom.name, atom_line[13:17].strip())
|
|
256
|
+
self.assertEqual(atom.residue_name, atom_line[17:21].strip())
|
|
257
|
+
self.assertEqual(atom.chain_id, atom_line[21:23].strip())
|
|
258
|
+
self.assertEqual(atom.residue_number, int(atom_line[23:27]))
|
|
259
|
+
self.assertAlmostEqual(atom.x, float(atom_line[31:39]), places=3)
|
|
260
|
+
self.assertAlmostEqual(atom.y, float(atom_line[39:47]), places=3)
|
|
261
|
+
self.assertAlmostEqual(atom.z, float(atom_line[47:55]), places=3)
|
|
262
|
+
self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
|
|
263
|
+
self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
|
|
264
|
+
|
|
265
|
+
atoms = hit.atoms(transform=False)
|
|
266
|
+
self.assertEqual(len(atoms), len(atom_lines))
|
|
267
|
+
for atom, atom_line in zip(atoms, atom_lines):
|
|
268
|
+
self.assertEqual(atom.serial, int(atom_line[7:12]))
|
|
269
|
+
self.assertEqual(atom.name, atom_line[13:17].strip())
|
|
270
|
+
self.assertEqual(atom.residue_name, atom_line[17:21].strip())
|
|
271
|
+
self.assertEqual(atom.chain_id, atom_line[21:23].strip())
|
|
272
|
+
self.assertEqual(atom.residue_number, int(atom_line[23:27]))
|
|
273
|
+
self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
|
|
274
|
+
self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
|
|
275
|
+
|
|
276
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
277
|
+
def test_mcsa_query_reorder(self):
|
|
278
|
+
with files(data).joinpath("1.3.3.tpl").open() as f:
|
|
279
|
+
template = Template.load(f)
|
|
280
|
+
jess = Jess([template])
|
|
281
|
+
with files(data).joinpath("1AMY.pdb").open() as f:
|
|
282
|
+
molecule = Molecule.load(f)
|
|
283
|
+
with files(data).joinpath("1AMY+1.3.3.txt").open() as f:
|
|
284
|
+
results = list(filter(None, f.read().split("REMARK")))
|
|
285
|
+
|
|
286
|
+
hits = list(jess.query(molecule, 2, 4, 4, reorder=True))
|
|
287
|
+
self.assertEqual(len(hits), len(results))
|
|
288
|
+
|
|
289
|
+
# `reorder=True` means that we may get results in a different order
|
|
290
|
+
# to Jess, so we need to match the hits in the file by residue number
|
|
291
|
+
# to make sure we compare them consistently.
|
|
292
|
+
|
|
293
|
+
results_by_serials = {}
|
|
294
|
+
for block in results:
|
|
295
|
+
lines = block.strip().splitlines()
|
|
296
|
+
serials = tuple([ int(line.split()[1]) for line in lines[1:-1] ])
|
|
297
|
+
results_by_serials[serials] = block
|
|
298
|
+
|
|
299
|
+
for hit in hits:
|
|
300
|
+
self.assertIs(hit.template, template)
|
|
301
|
+
block = results_by_serials[tuple(atom.serial for atom in hit.atoms(False))]
|
|
302
|
+
|
|
303
|
+
lines = block.strip().splitlines()
|
|
304
|
+
query_id, rmsd, template_id, _, determinant, _, logE = lines[0].split()
|
|
305
|
+
self.assertEqual(query_id, "1AMY")
|
|
306
|
+
self.assertAlmostEqual(float(rmsd), hit.rmsd, places=3)
|
|
307
|
+
self.assertAlmostEqual(float(determinant), hit.determinant, places=1)
|
|
308
|
+
self.assertAlmostEqual(float(logE), hit.log_evalue, places=1)
|
|
309
|
+
|
|
310
|
+
atom_lines = lines[1:-1]
|
|
311
|
+
atoms = hit.atoms()
|
|
312
|
+
self.assertEqual(len(atoms), len(atom_lines))
|
|
313
|
+
for atom, atom_line in zip(atoms, atom_lines):
|
|
314
|
+
self.assertEqual(atom.serial, int(atom_line[7:12]))
|
|
315
|
+
self.assertEqual(atom.name, atom_line[13:17].strip())
|
|
316
|
+
self.assertEqual(atom.residue_name, atom_line[17:21].strip())
|
|
317
|
+
self.assertEqual(atom.chain_id, atom_line[21:23].strip())
|
|
318
|
+
self.assertEqual(atom.residue_number, int(atom_line[23:27]))
|
|
319
|
+
self.assertAlmostEqual(atom.x, float(atom_line[31:39]), places=3)
|
|
320
|
+
self.assertAlmostEqual(atom.y, float(atom_line[39:47]), places=3)
|
|
321
|
+
self.assertAlmostEqual(atom.z, float(atom_line[47:55]), places=3)
|
|
322
|
+
self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
|
|
323
|
+
self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
|
|
324
|
+
|
|
325
|
+
atoms = hit.atoms(transform=False)
|
|
326
|
+
self.assertEqual(len(atoms), len(atom_lines))
|
|
327
|
+
for atom, atom_line in zip(atoms, atom_lines):
|
|
328
|
+
self.assertEqual(atom.serial, int(atom_line[7:12]))
|
|
329
|
+
self.assertEqual(atom.name, atom_line[13:17].strip())
|
|
330
|
+
self.assertEqual(atom.residue_name, atom_line[17:21].strip())
|
|
331
|
+
self.assertEqual(atom.chain_id, atom_line[21:23].strip())
|
|
332
|
+
self.assertEqual(atom.residue_number, int(atom_line[23:27]))
|
|
333
|
+
self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
|
|
334
|
+
self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
|
|
335
|
+
|
|
336
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
337
|
+
def test_ignore_chain_none(self):
|
|
338
|
+
with files(data).joinpath("4.1.2.tpl").open() as f:
|
|
339
|
+
template = Template.load(f)
|
|
340
|
+
jess = Jess([template])
|
|
341
|
+
with files(data).joinpath("5ayx.EF.pdb").open() as f:
|
|
342
|
+
molecule = Molecule.load(f)
|
|
343
|
+
|
|
344
|
+
hits = list(jess.query(molecule, 3, 3, 3, ignore_chain=None))
|
|
345
|
+
self.assertEqual(len(hits), 0)
|
|
346
|
+
|
|
347
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
348
|
+
def test_ignore_chain_residues(self):
|
|
349
|
+
with files(data).joinpath("4.1.2.tpl").open() as f:
|
|
350
|
+
template = Template.load(f)
|
|
351
|
+
jess = Jess([template])
|
|
352
|
+
with files(data).joinpath("5ayx.EF.pdb").open() as f:
|
|
353
|
+
molecule = Molecule.load(f)
|
|
354
|
+
|
|
355
|
+
hits = list(jess.query(molecule, 3, 3, 3, ignore_chain="residues"))
|
|
356
|
+
self.assertEqual(len(hits), 2)
|
|
357
|
+
for hit in hits:
|
|
358
|
+
atoms = hit.atoms(transform=False)
|
|
359
|
+
for i in range(1, len(atoms)):
|
|
360
|
+
if atoms[i-1].residue_number == atoms[i].residue_number:
|
|
361
|
+
self.assertEqual(atoms[i-1].chain_id, atoms[i].chain_id)
|
|
362
|
+
|
|
363
|
+
@unittest.skipUnless(files, "importlib.resources not available")
|
|
364
|
+
def test_ignore_chain_atoms(self):
|
|
365
|
+
with files(data).joinpath("4.1.2.tpl").open() as f:
|
|
366
|
+
template = Template.load(f)
|
|
367
|
+
jess = Jess([template])
|
|
368
|
+
with files(data).joinpath("5ayx.EF.pdb").open() as f:
|
|
369
|
+
molecule = Molecule.load(f)
|
|
370
|
+
|
|
371
|
+
hits = list(jess.query(molecule, 3, 3, 3, ignore_chain="atoms"))
|
|
372
|
+
self.assertEqual(len(hits), 7)
|
|
373
|
+
|
|
374
|
+
|