pyjess 0.5.1__cp38-cp38-win_amd64.whl → 0.5.2__cp38-cp38-win_amd64.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.

Binary file
pyjess/_jess.pyi CHANGED
@@ -183,6 +183,8 @@ class Query(Generic[_T], Iterator[Hit[_T]]):
183
183
  def __next__(self) -> Hit[_T]: ...
184
184
 
185
185
  class Hit(Generic[_T]):
186
+ def __getstate__(self) -> Dict[str, object]: ...
187
+ def __setstate__(self, state: Dict[str, object]) -> None: ...
186
188
  @property
187
189
  def rmsd(self) -> float: ...
188
190
  @property
pyjess/_jess.pyx CHANGED
@@ -1205,7 +1205,7 @@ cdef class Query:
1205
1205
  cdef bint _rewind(self) noexcept nogil:
1206
1206
  self._partial = True
1207
1207
 
1208
- cdef int _copy_atoms(self, _Template* tpl, Hit hit) except -1 nogil:
1208
+ cdef int _copy_atoms(self, const _Template* tpl, Hit hit) except -1 nogil:
1209
1209
  cdef _Atom** atoms = jess.jess.JessQuery_atoms(self._jq)
1210
1210
  cdef int count = tpl.count(tpl)
1211
1211
 
@@ -1216,6 +1216,15 @@ cdef class Query:
1216
1216
  memcpy(&hit._atoms[i], atoms[i], sizeof(_Atom))
1217
1217
  return count
1218
1218
 
1219
+ cdef int _copy_superposition(self, _Superposition* sup, Hit hit) noexcept nogil:
1220
+ cdef const double* M = jess.super.Superposition_rotation(sup)
1221
+ cdef const double* c = jess.super.Superposition_centroid(sup, 0)
1222
+ cdef const double* v = jess.super.Superposition_centroid(sup, 1)
1223
+ memcpy(hit._rotation, M, 9*sizeof(double))
1224
+ memcpy(hit._centre[0], c, 3*sizeof(double))
1225
+ memcpy(hit._centre[1], v, 3*sizeof(double))
1226
+ return 0
1227
+
1219
1228
  def __next__(self):
1220
1229
  assert self._jq is not NULL
1221
1230
 
@@ -1227,11 +1236,11 @@ cdef class Query:
1227
1236
  cdef Hit hit = Hit.__new__(Hit)
1228
1237
 
1229
1238
  # prepare the hit to be returned
1230
- hit._sup = NULL
1231
- hit._atoms = NULL
1232
1239
  hit.rmsd = INFINITY
1240
+ hit._atoms = NULL
1233
1241
  hit._molecule = self.molecule
1234
1242
  hit_tpl = NULL
1243
+ hit_found = False
1235
1244
 
1236
1245
  # search the next hit without the GIL to allow parallel queries.
1237
1246
  with nogil:
@@ -1240,14 +1249,13 @@ cdef class Query:
1240
1249
  # was obtained with the current template and not with the
1241
1250
  # previous one
1242
1251
  tpl = jess.jess.JessQuery_template(self._jq)
1243
- if hit._sup != NULL and hit_tpl != tpl:
1252
+ if hit_found and hit_tpl != tpl:
1244
1253
  self._rewind()
1245
1254
  break
1246
1255
 
1247
1256
  # load superposition and compute RMSD for the current iteration
1248
1257
  sup = jess.jess.JessQuery_superposition(self._jq)
1249
1258
  rmsd = jess.super.Superposition_rmsd(sup)
1250
- keep_sup = False
1251
1259
 
1252
1260
  # NB(@althonos): we don't need to compute the E-value to get the
1253
1261
  # best match by molecule/template pair since the
@@ -1272,22 +1280,20 @@ cdef class Query:
1272
1280
  stacklevel=2,
1273
1281
  )
1274
1282
  else:
1275
- if hit._sup != NULL:
1276
- jess.super.Superposition_free(hit._sup)
1277
1283
  self._copy_atoms(tpl, hit)
1278
- hit._sup = sup
1284
+ self._copy_superposition(sup, hit)
1279
1285
  hit.rmsd = rmsd
1280
1286
  hit_tpl = tpl
1287
+ hit_found = True
1281
1288
 
1282
1289
  # free superposition items that are not used in a hit, and
1283
1290
  # return hits immediately if we are not in best match mode
1284
1291
  self._candidates += 1
1285
- if hit._sup != sup:
1286
- jess.super.Superposition_free(sup)
1287
- if hit._sup != NULL and not self.best_match:
1292
+ jess.super.Superposition_free(sup)
1293
+ if hit_found and not self.best_match:
1288
1294
  break
1289
1295
 
1290
- if hit._sup == NULL:
1296
+ if not hit_found:
1291
1297
  raise StopIteration
1292
1298
 
1293
1299
  # get the template object for the hit
@@ -1305,7 +1311,8 @@ cdef class Hit:
1305
1311
  molecule (`~pyjess.Molecule`): The query molecule.
1306
1312
 
1307
1313
  """
1308
- cdef _Superposition* _sup
1314
+ cdef double[9] _rotation
1315
+ cdef double[2][3] _centre
1309
1316
  cdef _Atom* _atoms
1310
1317
 
1311
1318
  cdef readonly double rmsd
@@ -1313,19 +1320,49 @@ cdef class Hit:
1313
1320
  cdef Molecule _molecule
1314
1321
 
1315
1322
  def __dealloc__(self):
1316
- jess.super.Superposition_free(self._sup)
1317
1323
  free(self._atoms)
1318
1324
 
1325
+ def __getstate__(self):
1326
+ return {
1327
+ "rotation": list(self._rotation),
1328
+ "centre": list(self._centre),
1329
+ "atoms": self.atoms(transform=False),
1330
+ "rmsd": self.rmsd,
1331
+ "template": self.template,
1332
+ "molecule": self.molecule(transform=False),
1333
+ }
1334
+
1335
+ def __setstate__(self, state):
1336
+ cdef size_t i
1337
+ cdef size_t count
1338
+ cdef Atom atom
1339
+
1340
+ self.rmsd = state["rmsd"]
1341
+ self.template = state["template"]
1342
+ self._molecule = state["molecule"]
1343
+ self._rotation = state["rotation"]
1344
+ self._centre = state["centre"]
1345
+
1346
+ # check number of atoms is consistent
1347
+ count = len(self.template)
1348
+ if len(state["atoms"]) != count:
1349
+ raise ValueError(f"unexpected number of atoms: {len(state['atoms'])!r} (expected {count!r})")
1350
+ # allocate or reallocate memory for atoms
1351
+ self._atoms = <_Atom*> realloc(self._atoms, count * sizeof(_Atom))
1352
+ if self._atoms is NULL:
1353
+ raise MemoryError("Failed to allocate hit atoms")
1354
+ # copy atom data
1355
+ for i, atom in enumerate(state["atoms"]):
1356
+ memcpy(&self._atoms[i], atom._atom, sizeof(_Atom))
1357
+
1319
1358
  @property
1320
1359
  def determinant(self):
1321
1360
  """`float`: The determinant of the rotation matrix.
1322
1361
  """
1323
- assert self._sup is not NULL
1324
- cdef const double* p
1362
+ cdef const double* p = self._rotation
1325
1363
  cdef double det = 0.0
1326
1364
 
1327
1365
  with nogil:
1328
- p = jess.super.Superposition_rotation(self._sup)
1329
1366
  det += p[0] * (p[4] * p[8] - p[5] * p[7])
1330
1367
  det -= p[1] * (p[3] * p[8] - p[5] * p[6])
1331
1368
  det += p[2] * (p[3] * p[7] - p[4] * p[6])
@@ -1369,7 +1406,6 @@ cdef class Hit:
1369
1406
 
1370
1407
  """
1371
1408
  assert self.template._tpl is not NULL
1372
- assert self._sup is not NULL
1373
1409
 
1374
1410
  cdef Atom atom
1375
1411
  cdef int i
@@ -1378,21 +1414,23 @@ cdef class Hit:
1378
1414
  cdef int count = self.template._tpl.count(self.template._tpl)
1379
1415
  cdef list atoms = []
1380
1416
 
1381
- cdef const double* M = jess.super.Superposition_rotation(self._sup)
1382
- cdef const double* c = jess.super.Superposition_centroid(self._sup, 0)
1383
- cdef const double* v = jess.super.Superposition_centroid(self._sup, 1)
1417
+ cdef const double* M = self._rotation
1418
+ cdef const double* c = self._centre[0]
1419
+ cdef const double* v = self._centre[1]
1384
1420
 
1385
1421
  for k in range(count):
1386
-
1387
1422
  atom = Atom.__new__(Atom)
1388
- atom._atom = <_Atom*> malloc(sizeof(_Atom))
1389
- memcpy(atom._atom, &self._atoms[k], sizeof(_Atom))
1390
-
1391
1423
  if transform:
1424
+ atom._atom = <_Atom*> malloc(sizeof(_Atom))
1425
+ memcpy(atom._atom, &self._atoms[k], sizeof(_Atom))
1392
1426
  for i in range(3):
1393
1427
  atom._atom.x[i] = v[i]
1394
1428
  for j in range(3):
1395
1429
  atom._atom.x[i] += M[3*i + j] * (self._atoms[k].x[j] - c[j])
1430
+ else:
1431
+ atom.owned = True
1432
+ atom.owner = self
1433
+ atom._atom = &self._atoms[k]
1396
1434
 
1397
1435
  atoms.append(atom)
1398
1436
 
@@ -1413,16 +1451,15 @@ cdef class Hit:
1413
1451
 
1414
1452
  """
1415
1453
  assert self.template._tpl is not NULL
1416
- assert self._sup is not NULL
1417
1454
 
1418
1455
  cdef _Atom* atom
1419
1456
  cdef Molecule mol
1420
1457
  cdef size_t i
1421
1458
  cdef size_t j
1422
1459
  cdef size_t k
1423
- cdef const double* M = jess.super.Superposition_rotation(self._sup)
1424
- cdef const double* c = jess.super.Superposition_centroid(self._sup, 0)
1425
- cdef const double* v = jess.super.Superposition_centroid(self._sup, 1)
1460
+ cdef const double* M = self._rotation
1461
+ cdef const double* c = self._centre[0]
1462
+ cdef const double* v = self._centre[1]
1426
1463
 
1427
1464
  if not transform:
1428
1465
  return self._molecule
pyjess/tests/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from . import (
2
2
  test_atom,
3
+ test_hit,
3
4
  test_jess,
4
5
  test_molecule,
5
6
  test_template_atom,
@@ -8,6 +9,7 @@ from . import (
8
9
 
9
10
  def load_tests(loader, suite, pattern):
10
11
  suite.addTests(loader.loadTestsFromModule(test_atom))
12
+ suite.addTests(loader.loadTestsFromModule(test_hit))
11
13
  suite.addTests(loader.loadTestsFromModule(test_jess))
12
14
  suite.addTests(loader.loadTestsFromModule(test_molecule))
13
15
  suite.addTests(loader.loadTestsFromModule(test_template_atom))
@@ -0,0 +1,33 @@
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 TestHit(unittest.TestCase):
12
+
13
+ @unittest.skipUnless(files, "importlib.resources not available")
14
+ @classmethod
15
+ def setUpClass(cls):
16
+ with files(data).joinpath("template_01.qry").open() as f:
17
+ template = Template.load(f)
18
+ jess = Jess([template])
19
+ with files(data).joinpath("pdb1lnb.pdb").open() as f:
20
+ molecule = Molecule.load(f)
21
+
22
+ cls.hit = next(jess.query(molecule, 1, 2, 2))
23
+
24
+ def test_pickle(self):
25
+ hit = pickle.loads(pickle.dumps(self.hit))
26
+ self.assertIsNot(self.hit, hit)
27
+ self.assertEqual(self.hit.rmsd, hit.rmsd)
28
+ self.assertEqual(self.hit.determinant, hit.determinant)
29
+ self.assertEqual(self.hit.evalue, hit.evalue)
30
+ self.assertEqual(self.hit.template, hit.template)
31
+ self.assertListEqual(self.hit.atoms(transform=True), hit.atoms(transform=True))
32
+ self.assertListEqual(self.hit.atoms(transform=False), hit.atoms(transform=False))
33
+ self.assertEqual(self.hit.molecule(transform=False), hit.molecule(transform=False))
pyjess/tests/test_jess.py CHANGED
@@ -240,3 +240,14 @@ class TestJess(unittest.TestCase):
240
240
  self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
241
241
  self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
242
242
 
243
+ atoms = hit.atoms(transform=False)
244
+ self.assertEqual(len(atoms), len(atom_lines))
245
+ for atom, atom_line in zip(atoms, atom_lines):
246
+ self.assertEqual(atom.serial, int(atom_line[7:12]))
247
+ self.assertEqual(atom.name, atom_line[13:17].strip())
248
+ self.assertEqual(atom.residue_name, atom_line[17:21].strip())
249
+ self.assertEqual(atom.chain_id, atom_line[21:23].strip())
250
+ self.assertEqual(atom.residue_number, int(atom_line[23:27]))
251
+ self.assertAlmostEqual(atom.occupancy, float(atom_line[55:61]), places=3)
252
+ self.assertAlmostEqual(atom.temperature_factor, float(atom_line[61:67]), places=3)
253
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyjess
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Cython bindings and Python interface to JESS, a 3D template matching software.
5
5
  Keywords: bioinformatics,structure,template,matching
6
6
  Author-Email: Martin Larralde <martin.larralde@embl.de>
@@ -1,11 +1,11 @@
1
1
  pyjess/.gitignore,sha256=u14v4OOy8U50Kp9SUKU8DupCG-mQIuel47gdbNDmAwg,21
2
2
  pyjess/__init__.py,sha256=Xe9GBQUBm9ik-ty5tcE3UQ9Ip1p-C_IGvTPuGULolng,766
3
- pyjess/_jess.cp38-win_amd64.pyd,sha256=G4ncTJ_UUTga4ZGIxZaEdG_uaX2zTL-Mo2yfFX6XGfc,304640
4
- pyjess/_jess.pyi,sha256=oWlqpqnhOKFcq2UCpGJrUJaZZF1ZlLodKxINwoR3vrw,7118
5
- pyjess/_jess.pyx,sha256=hHDaW9FgJXln5uFQWadGZH5aQ1iAtzWvscIj-8MawEo,52130
3
+ pyjess/_jess.cp38-win_amd64.pyd,sha256=n0AJ1X2OrW9JYf5tZ7Wl_k6zfNvnrIQNdxDsJnImb78,318976
4
+ pyjess/_jess.pyi,sha256=1U7KeCDydiOT0vGts0sidGz_gI2PycD1sBiUmcafd7c,7239
5
+ pyjess/_jess.pyx,sha256=tyAyYZaYYm8-dAMDMrH6WrpV5hM8hnn9DYHh4idoAOA,53500
6
6
  pyjess/CMakeLists.txt,sha256=H9eXbrFcGF2OLP8muQctb4cOb27Qp2uZj5KRjoDAROg,36
7
7
  pyjess/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pyjess/tests/__init__.py,sha256=h83kBzYKH_i1InkM8mOA23zE3PBaB9lrNDCuhC8LOl4,544
8
+ pyjess/tests/__init__.py,sha256=J7rYASCuQsCu5gktf5XqjNxJoBkBqxbREAiaSOta5xE,617
9
9
  pyjess/tests/data/1.3.3.tpl,sha256=gleyiSSHAVJbRJaK8Nlh9setsj6EI38Sr1XU5OEduQE,1011
10
10
  pyjess/tests/data/1AMY+1.3.3.txt,sha256=Wyq9Eh9QVaOPH_jsZ6iF9WYhFdTGESqOzjfX14-0gAo,105456
11
11
  pyjess/tests/data/1AMY.pdb,sha256=fIbowuYS46hQh82xBtVaIPC50o7U08CnHNcnq4nM944,323162
@@ -14,12 +14,13 @@ pyjess/tests/data/pdb1lnb.pdb,sha256=F8A6OdRly5c-pxsDw1LjTFINI75r1HaKaYB_eXv1QuM
14
14
  pyjess/tests/data/template_01.qry,sha256=izCIhUUTEk-IvQowhSVLiJaCAhpPbyvrfyoR4Q6-Pm0,616
15
15
  pyjess/tests/data/template_02.qry,sha256=5IYRTqsvO_roB2INLwfFDEaWJW9VRcXdbK4oe8VKMxE,618
16
16
  pyjess/tests/test_atom.py,sha256=clLN9IVuivadztGtagDhdPBDGoMkUgs41lEWuTCCmFA,4741
17
- pyjess/tests/test_jess.py,sha256=EEiPW-CtdFa3RLoI1TTSloBhtmj3kvhy987GUAexMJM,10884
17
+ pyjess/tests/test_hit.py,sha256=3p7MkvZL84e-tSbVlMSXHbO1yCZkaLIMD2e09occw1A,1244
18
+ pyjess/tests/test_jess.py,sha256=Hp12b3xkRX0U8RFcejwDPFTEX8JzpOQTF6_zMXYAWDM,11616
18
19
  pyjess/tests/test_molecule.py,sha256=9k6uiTeOWc5NiO7epyxY9lm_GgksPb7-o-ZcNFNxutw,5452
19
20
  pyjess/tests/test_template.py,sha256=AIN-ba5-YTnGdT9SGPU4q45AZ03QnPE769WyItSpoPs,4657
20
21
  pyjess/tests/test_template_atom.py,sha256=oK8cfKe4_k3Pm1PqoTTxTzAoeUVLiCFsg6QmiTQ-RCQ,3496
21
22
  pyjess/tests/utils.py,sha256=Z7rUPC-D8dZlRfHAnLaXHUg6M10D3zFvNiwDvvHA3xc,202
22
- pyjess-0.5.1.dist-info/METADATA,sha256=OMnKlTvBTrR8tfxUFdUJXnJPezgo10GrHWTxap3eG7A,11248
23
- pyjess-0.5.1.dist-info/WHEEL,sha256=AmELy_2Xx7O_V7LBv-s-ztFbR13e4jkKGwV7sVzppgU,104
24
- pyjess-0.5.1.dist-info/licenses/COPYING,sha256=Iyx2bRDPnLgoEzW2KVanb61cjhW8lnhJNU-mjS-KhIY,1124
25
- pyjess-0.5.1.dist-info/RECORD,,
23
+ pyjess-0.5.2.dist-info/METADATA,sha256=tsCMCW4Qh7vkECoA8aybf9sb0I8QTcdifZ7P7SDm1oI,11248
24
+ pyjess-0.5.2.dist-info/WHEEL,sha256=yXMtVL9U8RkqJEJfb-z5X2s1_G1r2eGG-REYk3wgjZ0,104
25
+ pyjess-0.5.2.dist-info/licenses/COPYING,sha256=Iyx2bRDPnLgoEzW2KVanb61cjhW8lnhJNU-mjS-KhIY,1124
26
+ pyjess-0.5.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: scikit-build-core 0.11.5
2
+ Generator: scikit-build-core 0.11.6
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp38-cp38-win_amd64
5
5