pyjess 0.7.0__cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.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.

@@ -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
@@ -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
+