Files
pymol-open-source/testing/tests/api/importing.py
2025-05-13 01:10:54 -04:00

721 lines
27 KiB
Python

import os
import sys
import socket
from pathlib import Path
from tempfile import TemporaryDirectory
import requests
import pymol
from pymol import cmd, testing
pdbstr = '''ATOM 1 N GLY 22 -1.195 0.201 -0.206 1.00 0.00 N
ATOM 2 CA GLY 22 0.230 0.318 -0.502 1.00 0.00 C
ATOM 3 C GLY 22 1.059 -0.390 0.542 1.00 0.00 C
ATOM 4 O GLY 22 0.545 -0.975 1.499 1.00 0.00 O
ATOM 5 H GLY 22 -1.558 -0.333 0.660 1.00 0.00 H
ATOM 6 3HA GLY 22 0.482 1.337 -0.514 0.00 0.00 H
ATOM 7 HA GLY 22 0.434 -0.159 -1.479 1.00 0.00 H
END
'''
molstr = '''glycine
ChemPy 3D 0
7 6 0 0 1 0 0 0 0 0999 V2000
-1.1946 0.2011 -0.2061 N 0 0 0 0 0 0 0 0 0 0 0 0
0.2304 0.3181 -0.5021 C 0 0 0 0 0 0 0 0 0 0 0 0
1.0594 -0.3899 0.5419 C 0 0 0 0 0 0 0 0 0 0 0 0
0.5454 -0.9749 1.4989 O 0 0 0 0 0 0 0 0 0 0 0 0
-1.5576 -0.3329 0.6599 H 0 0 0 0 0 0 0 0 0 0 0 0
0.4824 1.3374 -0.5137 H 0 0 0 0 0 0 0 0 0 0 0 0
0.4344 -0.1589 -1.4791 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
1 5 1 0 0 0 0
2 3 1 0 0 0 0
2 6 1 0 0 0 0
2 7 1 0 0 0 0
3 4 2 0 0 0 0
M END
'''
mmodstr = ''' 7 gly
34 2 1 5 1 0 0 0 0 0 0 0 0 -1.195000 0.201000 -0.206000 22G 38 0.00000 0.00000 GLY N
3 1 1 3 1 6 1 7 1 0 0 0 0 0.230000 0.318000 -0.502000 22G 2 0.00000 0.00000 GLY CA
7 2 1 4 2 0 0 0 0 0 0 0 0 1.059000 -0.390000 0.542000 22G 2 0.00000 0.00000 GLY C
15 3 2 0 0 0 0 0 0 0 0 0 0 0.545000 -0.975000 1.499000 22G 75 0.00000 0.00000 GLY O
44 1 1 0 0 0 0 0 0 0 0 0 0 -1.558000 -0.333000 0.660000 22G 21 0.00000 0.00000 GLY H
41 2 1 0 0 0 0 0 0 0 0 0 0 0.482000 1.337000 -0.514000 22G 21 0.00000 0.00000 GLY 3HA
41 2 1 0 0 0 0 0 0 0 0 0 0 0.434000 -0.159000 -1.479000 22G 21 0.00000 0.00000 GLY HA
'''
def _get_free_port() -> int:
with socket.socket() as s:
s.bind(("", 0))
return s.getsockname()[1]
class TestImporting(testing.PyMOLTestCase):
@testing.requires('network')
def testFetch(self):
with testing.mkdtemp() as fetch_path:
names = []
cmd.set('fetch_path', fetch_path)
cmd.set('fetch_host', 'pdb pdbe')
cmd.fetch('1avy', '1avy1', type='pdb1')
names += ['1avy1']
self.assertItemsEqual(cmd.get_names(), names)
self.assertEqual(cmd.count_states('1avy1'), 3)
if testing.PYMOL_VERSION_TUPLE < (2, 0):
self.skipTest('upstream download URL has changed')
cmd.fetch('1avy', type='2fofc')
names += ['1avy_2fofc']
self.assertItemsEqual(cmd.get_names(), names)
self.assertEqual(cmd.get_type('1avy_2fofc'), 'object:map')
def testFetchLocal(self):
try:
import urllib.parse as urlparse
except ImportError:
import urlparse
if os.getenv('GITHUB_ACTIONS') and sys.platform == 'win32':
self.skipTest('Temporarily skip this test in GHA')
return
# PyMOL 1.8.6 adds full URLs, remove them
pdbpaths = pymol.importing.hostPaths['pdb']
if isinstance(pdbpaths, list):
pdbpaths[:] = [p for p in pdbpaths if '://' not in p]
with testing.mkdtemp() as fetch_path:
names = []
cmd.set('fetch_path', fetch_path)
cmd.set('fetch_host', urlparse.urlunsplit(['file', '',
self.datafile('pdb.mirror'), '', '']))
cmd.fetch('1avy', type='pdb')
names += ['1avy']
self.assertItemsEqual(cmd.get_names(), names)
cmd.fetch('1avyB', type='pdb')
names += ['1avyB']
self.assertItemsEqual(cmd.get_names(), names)
self.assertEqual(cmd.get_chains('1avyB'), ['B'])
cmd.fetch('1aq5', type='pdb', multiplex=1)
names += ['1aq5_%04d' % (i+1) for i in range(20)]
self.assertItemsEqual(cmd.get_names(), names)
def testFinishObject(self):
# Disclaimer: I don't know the relevance of load(..., finish=0) and
# finish_object(), but it does call ObjectMoleculeUpdateIDNumbers
# so I'll just test that.
cmd.load(self.datafile("1ehz-5.pdb"), "m1", finish=0)
cmd.alter('all', 'ID = -1')
self.assertEqual(cmd.identify('last all'), [-1])
cmd.finish_object('m1')
self.assertEqual(cmd.identify('last all'), [224])
# non-existing object name should throw
self.assertRaises(pymol.CmdException, lambda: cmd.finish_object('m2'))
def testLoad_append_state(self):
filename = self.datafile("1ehz-5.pdb")
cmd.load(filename)
cmd.load(filename, format="pdb")
self.assertEqual(cmd.get_names(), ["1ehz-5"])
self.assertEqual(cmd.count_atoms(), 112)
self.assertEqual(cmd.count_states(), 2)
def testLoad_replace_state(self):
filename = self.datafile("1ehz-5.pdb")
cmd.load(filename)
cmd.load(filename, state=1)
self.assertEqual(cmd.get_names(), ["1ehz-5"])
self.assertEqual(cmd.count_atoms(), 112)
self.assertEqual(cmd.count_states(), 1)
def testLoad_state_skip(self):
filename = self.datafile("1ehz-5.pdb")
cmd.load(filename)
cmd.load(filename, state=3)
self.assertEqual(cmd.count_states(), 3)
def testLoad_no_zoom(self):
view = cmd.get_view()
cmd.load(self.datafile("1ehz-5.pdb"), zoom=0)
self.assertEqual(view, cmd.get_view())
@testing.requires('incentive')
def testLoad_mimic(self):
filename = self.datafile("repr.mae")
cmd.load(filename, "m0", mimic=0)
cmd.load(filename, "m1", mimic=1)
self.assertFalse(
cmd.get_setting_boolean("stick_ball", "m0.x_ballstick", state=1))
self.assertTrue(
cmd.get_setting_boolean("stick_ball", "m1.x_ballstick", state=1))
@testing.requires_version('1.7.3.0')
def testLoad_idx(self):
cmd.load(self.datafile('desmond/Bace_mapper_20143_3a51a59_e85111a_solvent_11_replica0-out.idx'), state=1)
self.assertEqual(cmd.count_states(), 209)
self.assertEqual(cmd.count_atoms(), 2482)
def testLoad_pqr(self):
cmd.load(self.datafile('example.pqr'))
charges = []
radii = []
n = cmd.iterate('all', 'charges.append(partial_charge);radii.append(elec_radius)', space=locals())
self.assertEqual(n, 191)
self.assertTrue(any(x != 0.0 for x in charges))
self.assertTrue(any(x != 0.0 for x in radii))
@testing.requires_version('2.2')
def testLoad_pqr_various(self):
import glob
pqrdir = self.datafile('pqr')
extent_expect = {
19: [[1999.32, 2998.77, -901.70], [2008.4, 3006.35, -898.02]],
36: [[1998.629, 2998.033, -902.509], [2008.765, 3006.347, -898.022]],
}
for filename in glob.glob(os.path.join(pqrdir, '*.pqr')):
cmd.load(filename)
n_atom = cmd.count_atoms()
extent = cmd.get_extent()
self.assertArrayEqual(extent, extent_expect[n_atom], delta=1e-2, msg=filename)
if 'chain' in os.path.basename(filename):
self.assertEqual(cmd.get_chains(), ['A'])
else:
self.assertEqual(cmd.get_chains(), [''])
cmd.delete('*')
@testing.foreach.product(
['sdf', 'mol2', 'xyz', 'pdb', 'mmd'],
[0, 1],
)
def testLoad_multi(self, ext, discrete):
'''
Load multi-state files with discrete=0/1 and multiplex=0/1
'''
N = 10
filename = self.datafile('ligs3d.' + ext)
# mutiplex=0
cmd.load(filename, discrete=discrete, multiplex=0)
if testing.PYMOL_VERSION_TUPLE >= (1, 7):
self.assertEqual(cmd.count_discrete('*'), discrete)
self.assertEqual(cmd.count_states(), N)
self.assertEqual(len(cmd.get_object_list()), 1)
if ext in ['mmd']:
return
# mutiplex=1
cmd.delete('*')
cmd.load(filename, discrete=discrete, multiplex=1)
if testing.PYMOL_VERSION_TUPLE >= (1, 7):
self.assertEqual(cmd.count_discrete('*'), discrete * N)
self.assertEqual(cmd.count_states(), 1)
self.assertEqual(len(cmd.get_object_list()), N)
@testing.foreach(
['.ccp4', True],
['.brix', True],
['.spi', False],
)
@testing.requires_version('1.7.3.0')
def testLoad_map(self, ext, check_extent):
filename = self.datafile('emd_1155' + ext)
if not os.path.exists(filename):
self.skipTest("missing " + filename)
cmd.load(filename, 'map1')
field = cmd.get_volume_field('map1', copy=0)
self.assertEqual(field.shape, (141, 91, 281))
if check_extent:
extent = cmd.get_extent('map1')
self.assertArrayEqual(extent, [[0.0, 0.0, 0.0], [2296.0, 1476.0, 4592.0]], delta=1e-2)
@testing.requires_version('1.7.3.0')
def testLoad_cube(self):
cmd.load(self.datafile('h2o-elf.cube'))
extent = cmd.get_extent('h2o-elf')
self.assertArrayEqual(extent, [
[ -0.075, -0.075, -0.075],
[ 5.925, 5.925, 5.925]], delta=1e3)
field = cmd.get_volume_field('h2o-elf', copy=0)
self.assertEqual(field.shape, (40, 40, 40))
self.assertAlmostEqual(field.mean(), 0.06915, delta=1e-4)
def _testLoad_dx(self, filename):
cmd.load(self.datafile(filename), 'map1')
extent = cmd.get_extent('map1')
self.assertArrayEqual(extent, [[1.0, 2.0, 3.0], [5.0, 7.0, 9.0]], delta=1e-2)
def testLoad_dx(self):
self._testLoad_dx('mapaligned.dx')
self._testLoad_dx('mapnumeric.dx')
@testing.requires_version('2.1')
def testLoad_dx_skewed(self):
self._testLoad_dx('mapskewed.dx')
@testing.requires_version('2.5')
def testLoad_dxstr(self):
with open(self.datafile('mapaligned.dx'), 'rb') as handle:
cmd.load_raw(handle.read(), 'dx', 'map1')
extent = cmd.get_extent('map1')
self.assertArrayEqual(extent, [[1.0, 2.0, 3.0], [5.0, 7.0, 9.0]], delta=1e-2)
def testLoadBrick(self):
cmd.load_brick
self.skipTest("TODO")
def testLoadCallback(self):
cmd.load_callback
self.skipTest("TODO")
def testLoadCgo(self):
cmd.load_cgo
self.skipTest("TODO")
def testLoadEmbedded(self):
cmd.load(self.datafile("embed.p1m"))
self.assertEqual(6, cmd.count_atoms())
self.assertEqual(2, cmd.count_atoms('elem O'))
def testLoadMap(self):
cmd.load_map
self.skipTest("TODO")
def testLoadModel(self):
cmd.fragment('gly')
m = cmd.get_model()
cmd.delete('*')
cmd.load_model(m, 'm1')
self.assertEqual(7, cmd.count_atoms())
def testLoadObject(self):
cmd.load_object
self.skipTest("TODO")
def testLoadRaw(self):
cmd.load_raw(open(self.datafile("sampletrajectory.pdb")).read(), "pdb")
self.assertEqual(115, cmd.count_atoms())
@testing.requires_version('2.3.3')
def testLoadRawMMTF(self):
import gzip
with gzip.open(self.datafile("3njw.mmtf.gz")) as handle:
cmd.load_raw(handle.read(), "mmtf")
self.assertEqual(169, cmd.count_atoms())
@testing.requires_version('2.5')
def testLoadRawGRO(self):
cmd.load_raw(open(self.datafile("sampletrajectory.gro")).read(), "gro")
self.assertEqual(115, cmd.count_atoms())
@testing.requires_version('2.4')
def testLoadMMTFStr(self):
# deprecated
import gzip
with gzip.open(self.datafile("3njw.mmtf.gz")) as handle:
cmd.load(handle.read(), "m1", format="mmtfstr")
self.assertEqual(169, cmd.count_atoms())
@testing.foreach(
['.pdb', '.dcd'],
['.pdb', '.crd'],
['.gro', '.xtc'],
)
@testing.requires_version('1.7.3.0')
def testLoadTraj(self, topext, trjext):
pdbfile = self.datafile("sampletrajectory" + topext)
dcdfile = self.datafile("sampletrajectory" + trjext)
cmd.load(pdbfile)
cmd.load_traj(dcdfile, state=0)
self.assertEqual(11, cmd.count_states())
cmd.delete('*')
cmd.load(pdbfile)
cmd.load_traj(dcdfile, state=1, interval=2, max=3)
self.assertEqual(3, cmd.count_states())
cmd.delete('*')
cmd.load(pdbfile)
cmd.load_traj(dcdfile, state=1, start=3, stop=5)
self.assertEqual(3, cmd.count_states())
cmd.delete('*')
cmd.load(pdbfile)
cmd.load_traj(dcdfile, state=1, stop=9, average=3)
self.assertEqual(3, cmd.count_states())
cmd.delete('*')
# Changed in PyMOL 2.5: Default is now state=1 instead of state=0
@testing.requires_version('2.5')
def testLoadTraj_default_state_1(self):
cmd.load(self.datafile("sampletrajectory.pdb"))
cmd.load_traj(self.datafile("sampletrajectory.dcd"))
self.assertEqual(10, cmd.count_states())
# via ObjectMoleculeLoadTRJFile
@testing.requires_version('1.7')
def testLoadTraj_selection_trj(self):
base = self.datafile("sampletrajectory")
cmd.load(base + ".pdb")
cmd.load_traj(base + ".crd", selection="backbone", format="trj", state=0)
self.assertEqual(55, cmd.count_atoms('state 10'))
# via PlugIOManager
@testing.requires_version('2.4')
def testLoadTraj_selection(self):
base = self.datafile("sampletrajectory")
cmd.load(base + ".gro")
cmd.load_traj(base + ".xtc", selection="backbone", state=0)
self.assertEqual(55, cmd.count_atoms('state 10'))
@testing.requires_version('1.8.5')
def testLoadCharmmCor(self):
# http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/corplugin.html
for fmt in ['', 'cor']:
cmd.load(self.datafile("charmm.crd"), format=fmt)
self.assertEqual(81, cmd.count_atoms(), 'fmt: ' + fmt)
cmd.delete('*')
def testLoadTOP(self):
'''
Data files from:
http://ambermd.org/tutorials/basic/tutorial2/section6.htm
'''
cmd.load(self.datafile("TRPcage.top"))
cmd.load_traj(self.datafile("heat1.crd"), "TRPcage", format="trj", state=0)
self.assertEqual(304, cmd.count_atoms())
self.assertEqual(10, cmd.count_states())
@testing.requires_version('1.7.5')
def testLoadPSF(self):
cmd.load(self.datafile("ubiquitin.psf"))
self.assertEqual(26190, cmd.count_atoms())
self.assertEqual(0, cmd.count_states())
@testing.requires_version('1.7.5')
def testLoadVaspCHGCAR(self):
cmd.load(self.datafile("vasp.CHGCAR"), 'vasp.CHGCAR')
self.assertEqual(cmd.get_type('vasp.CHGCAR'), 'object:map')
extend = cmd.get_extent('vasp.CHGCAR')
self.assertArrayEqual(extend, [[0.0, 0.0, 0.0], [6.5, 6.5, 7.7]], delta=1e-2)
@testing.requires_version('1.7.5')
def testLoadVaspOUTCAR(self):
cmd.load(self.datafile("vasp.OUTCAR"))
self.assertEqual(2, cmd.count_atoms())
self.assertEqual(11, cmd.count_states())
@testing.requires_version('1.7.5')
def testLoadVaspPOSCAR(self):
cmd.load(self.datafile("vasp.POSCAR"))
self.assertEqual(2, cmd.count_atoms())
self.assertEqual(1, cmd.count_states())
@testing.requires_version('1.8.5.0')
def testLoadMSMSSurface(self):
cmd.load(self.datafile('surface.face'))
e = cmd.get_extent('surface')
self.assertArrayEqual(e, [
[28.003, 25.573, 12.883],
[34.238, 31.434, 17.835]], delta=1e-3)
@testing.requires_version('1.7') # broken before
def testReadMmodstr(self):
cmd.read_mmodstr(mmodstr, 'm1')
self.assertEqual(7, cmd.count_atoms())
def testReadMolstr(self):
cmd.read_molstr(molstr, 'm1')
self.assertEqual(7, cmd.count_atoms())
def testReadPdbstr(self):
cmd.read_pdbstr(pdbstr, 'm1')
self.assertEqual(7, cmd.count_atoms())
cmd.read_pdbstr(pdbstr, 'm1')
self.assertEqual(2, cmd.count_states())
def testReadSdfstr(self):
sdfstr = molstr + '$$$$\n'
cmd.read_sdfstr(sdfstr, 'm1')
self.assertEqual(7, cmd.count_atoms())
@testing.requires_version('1.8.3.1')
def testLoadSDFV3000(self):
cmd.load(self.datafile("v3000.sdf"))
self.assertEqual(12, cmd.count_atoms())
self.assertEqual( 1, cmd.count_atoms('formal_charge = +1'))
self.assertEqual( 1, cmd.count_atoms('formal_charge = -1'))
self.assertEqual( 6, cmd.count_atoms('elem C'))
self.assertEqual( 6, cmd.count_atoms('elem H'))
self.assertEqual( 4, cmd.count_atoms('(first elem H) extend 2'))
def testReadXplorstr(self):
cmd.read_xplorstr
self.skipTest("TODO")
def testSetSession(self):
# see TestExporting.testGetSession
pass
def testSpace(self):
cmd.space('pymol', 0.5)
cmd.space('cmyk', 0.7)
cmd.space('rgb')
# CmdException before 2.5, now QuietException (from Shortcut)
self.assertRaises((pymol.CmdException, cmd.QuietException),
lambda: cmd.space('no-such-space'))
pymol_data = os.environ['PYMOL_DATA']
os.environ['PYMOL_DATA'] = '/no/such/dir'
pymol_path = os.environ['PYMOL_PATH'] # PyMOL 1.x
os.environ['PYMOL_PATH'] = '/no/such/dir' # PyMOL 1.x
try:
self.assertRaises(pymol.CmdException, lambda: cmd.space('cmyk'))
finally:
os.environ['PYMOL_DATA'] = pymol_data
os.environ['PYMOL_PATH'] = pymol_path # PyMOL 1.x
@testing.requires_version('1.7.3.0')
def testLoadCoords(self):
import numpy
cmd.fragment('gly', 'm1')
coords = cmd.get_coords('m1')
coords += 5.0
cmd.load_coords(coords, 'm1')
self.assertTrue(numpy.allclose(coords, cmd.get_coords('m1')))
@testing.requires_version('1.7.3.0')
def testLoadCoordset(self):
import numpy
cmd.fragment('gly', 'm1')
coords = cmd.get_coordset('m1')
cmd.load_coordset(coords, 'm1', state=2)
self.assertEqual(2, cmd.count_states('m1'))
# data manipulation with copy=0
cmd.get_coordset('m1', copy=0)[:] += 5.0
self.assertTrue(numpy.allclose(coords + 5.0, cmd.get_coords('m1')))
@testing.requires_version('1.7.7')
def testLoadPDBML(self):
cmd.load(self.datafile("1ubq.xml.gz"))
self.assertEqual(660, cmd.count_atoms())
symmetry = cmd.get_symmetry()
self.assertArrayEqual(symmetry[:6], [50.84, 42.77, 28.95, 90.0, 90.0, 90.0], delta=1e-4)
self.assertEqual(symmetry[6], 'P 21 21 21')
@testing.requires_version('1.7.7')
def testLoadCML(self):
cmd.load(self.datafile("GLY.cml"))
self.assertEqual(10, cmd.count_atoms())
@testing.requires_version('1.7.7')
def testLoadPDBQT(self):
cmd.set('retain_order')
cmd.load(self.datafile("NSC7810.pdbqt"))
charges = []
n = cmd.iterate('all', 'charges.append(partial_charge)', space=locals())
self.assertEqual(n, 26)
charges_expected = [0.002, 0.012, -0.024, 0.012, 0.002, 0.019, 0.052,
0.002, -0.013, 0.013, -0.013, 0.002, 0.013, -0.024, 0.052,
0.012, 0.012, 0.002, 0.002, 0.019, 0.21, -0.644, -0.644,
0.21, -0.644, -0.644]
self.assertArrayEqual(charges, charges_expected, delta=1e-4)
@testing.requires_version('2.6')
def testLoadPLY(self):
cmd.load(self.datafile("test_PHE_pentamer.ply.gz"))
e = cmd.get_extent('test_PHE_pentamer')
self.assertArrayEqual(e, [[-3.141,-3.036,-2.809], [15.920, 10.425, 8.680]], delta=1e-3)
@testing.requires_version('1.8.4')
def testLoadMMTF(self):
cmd.load(self.datafile("3njw.mmtf.gz"))
self.assertEqual(169, cmd.count_atoms())
self.assertEqual(36, cmd.count_atoms('ss S'))
self.assertEqual(25, cmd.count_atoms('solvent'))
self.assertEqual(25, cmd.count_atoms('not polymer'))
symmetry = cmd.get_symmetry()
self.assertArrayEqual(symmetry[:6], [19.465, 21.432, 29.523, 90.0, 90.0, 90.0], delta=1e-4)
self.assertEqual(symmetry[6], 'P 21 21 21')
@testing.requires_version('2.6')
def testLoadMMTF_polymer(self):
cmd.load(self.datafile("1x8x.mmtf.gz"))
self.assertEqual(2780, cmd.count_atoms())
self.assertEqual(2544, cmd.count_atoms('polymer'))
self.assertEqual(218, cmd.count_atoms('solvent'))
self.assertEqual(13, cmd.count_atoms('organic'))
self.assertEqual(5, cmd.count_atoms('inorganic'))
@testing.requires_version('1.8.4')
def testLoadMMTFEmpty(self):
cmd.load(self.datafile("mmtf/empty-all0.mmtf"))
self.assertEqual(cmd.count_states(), 0)
cmd.delete('*')
cmd.load(self.datafile("mmtf/empty-numModels1.mmtf.gz"))
self.assertEqual(cmd.count_atoms(), 0)
self.assertEqual(cmd.get_names(), ["empty-numModels1"])
cmd.delete('*')
cmd.load(self.datafile("mmtf/empty-numChains1.mmtf.gz"))
self.assertEqual(cmd.count_atoms(), 0)
self.assertEqual(cmd.get_names(), ["empty-numChains1"])
cmd.delete('*')
cmd.load(self.datafile("mmtf/empty-mmtfVersion99999999.mmtf"))
self.assertEqual(cmd.get_names(), [])
cmd.delete('*')
@testing.requires_version('2.3.3')
def testLoadMMTFMissingOptionalGroupTypeFields(self):
cmd.load(self.datafile("mmtf/missing-optional-grouptype-fields.mmtf.gz"))
self.assertEqual(cmd.count_atoms(), 17)
self.assertEqual(len(cmd.get_bonds()), 7)
@testing.foreach(
['', '*', True],
['', 'pdb_header', True],
['', 'x pdb_header y', True],
['', 'other', False],
['', None, False],
['other', None, False],
['pdb_header', None, True],
['x pdb_header y', None, True],
['*', None, True],
)
@testing.requires_version('1.8.4')
@testing.requires('incentive')
def testPdbHeader(self, load_object_props_default, object_props, truth):
cmd.set('load_object_props_default', load_object_props_default)
cmd.load(self.datafile('1rx1.pdb'), 'm1', object_props=object_props)
self.assertEqual(truth, 'pdb_header' in (cmd.get_property_list('m1') or ()))
@testing.requires_version('2.4')
@testing.requires(
'network'
) # doesn't use external network, but is very slow while being connected to VPN
def testLoadPWG(self):
content_index = b"Hello World\n"
port = _get_free_port()
base_url = f"http://localhost:{port}"
with TemporaryDirectory() as root_dir:
root_dir = Path(root_dir)
index_file = root_dir / "index.html"
start_pwg_file = root_dir / "start.pwg"
index_file.write_bytes(content_index)
pwg_content = (
f"root {root_dir}\n"
f"port {port}\n"
"header add Test-Key Test-Value\n"
)
start_pwg_file.write_text(pwg_content)
cmd.load(str(start_pwg_file))
response = requests.get(url=base_url, timeout=5)
response.raise_for_status()
self.assertEqual(response.headers["Test-Key"], "Test-Value")
self.assertEqual(response.content, content_index)
# Warning: can't call locking functions here, will dead-lock
# get_version is non-locking since 1.7.4
response = requests.get(f"{base_url}/apply/pymol.cmd.get_version", timeout=5)
response.raise_for_status()
content = response.content.decode("ascii", errors="ignore")
self.assertTrue(content, cmd.get_version()[0] in content)
@testing.requires_version('2.1')
def testChemCompCartnUse(self):
xyz_model = (1., 2., 3.)
xyz_ideal = (4., 5., 6.)
xyz_short = (7., 8., 9.)
for (value, xyz) in [
(0x00, xyz_ideal),
(0x01, xyz_ideal),
(0x02, xyz_model),
(0x03, xyz_ideal),
(0x04, xyz_short),
(0x05, xyz_ideal),
(0x06, xyz_model),
(0x07, xyz_ideal),
]:
cmd.set('chem_comp_cartn_use', value)
cmd.load(self.datafile('chem_comp-fe.cif'), 'm1')
self.assertArrayEqual(xyz, cmd.get_coords('m1').reshape(-1))
cmd.delete('*')
@testing.requires_version('2.1')
def testCifMissing(self):
N = 7
cmd.fragment('gly', 'm1')
cmd.alter('all', '(chain, segi, resv, alt) = ("?", ".", 5, "")')
s = cmd.get_str('cif')
self.assertTrue("'?'" in s or '"?"' in s) # chain
self.assertTrue("'.'" in s or '"."' in s) # segi
self.assertTrue(' ? ' in s) # e.g. pdbx_PDB_ins_code
self.assertTrue(' . ' in s) # e.g. label_alt_id
cmd.delete('*')
cmd.set('cif_keepinmemory')
cmd.load(s, 'm2', format='cifstr')
self.assertEqual(['?'], cmd.get_chains())
self.assertEqual(cmd.count_atoms('segi .'), N)
self.assertEqual(cmd.count_atoms('alt ""'), N) # no alt
self.assertEqual(cmd.count_atoms('resi 5'), N) # no ins_code
from pymol.querying import cif_get_array
self.assertEqual(cif_get_array("m2", "_atom_site.type_symbol"), list('NCCOHHH'))
self.assertEqual(cif_get_array("m2", "_atom_site.id", "i"), list(range(1, N + 1)))
self.assertEqual(cif_get_array("m2", "_atom_site.auth_asym_id"), ['?'] * N)
self.assertEqual(cif_get_array("m2", "_atom_site.label_asym_id"), ['.'] * N)
self.assertEqual(cif_get_array("m2", "_atom_site.pdbx_pdb_ins_code"), [None] * N)
self.assertEqual(cif_get_array("m2", "_atom_site.label_alt_id"), [None] * N)
@testing.requires_version('2.4')
def testCifAltAtomId(self):
cmd.load(self.datafile('sia-alt-id.cif'), 'm1')
self.assertEqual(cmd.count_atoms('bound_to name C1'), 3)
self.assertEqual(cmd.count_atoms('(bound_to name C1) and name C3'), 0)
@testing.requires_version('2.5')
def testCifErrorHandling(self):
with self.assertRaisesRegex(pymol.CmdException,
'Parsing CIF file failed: expected key'):
cmd.load_raw('data_foo _k.a 1 2 3', 'cif', 'm1')
with self.assertRaisesRegex(pymol.CmdException,
'Parsing CIF file failed: truncated loop'):
cmd.load_raw('data_foo loop_ _k.a _k.b 1 2 3', 'cif', 'm2')
def testLoad_cif_map(self):
filename = self.datafile("cif_map.cif")
cmd.load(filename, 'cif_map')
field = cmd.get_volume_field('cif_map')
self.assertEqual(field.shape, (12, 12, 12))