Skip to content

Commit

Permalink
Squashed 'modules/core/dependency/python-ihm/' changes from 993cfebf3…
Browse files Browse the repository at this point in the history
…4..487413476a

487413476a Read/write alternate locations, closes ihmwg/python-ihm#146
82370afc0b Support ihm_modeling_protocol.details, relates ihmwg/python-ihm#145
de381f0969 Remove obsolete file
5dbceb7772 Use latest codecov action with token
f584b404b9 Render numpy 2 ints correctly in output mmCIF

git-subtree-dir: modules/core/dependency/python-ihm
git-subtree-split: 487413476a38edab220c97590887532a51c55fa5
  • Loading branch information
benmwebb committed Jul 12, 2024
1 parent 3a79478 commit c95a236
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 23 deletions.
1 change: 0 additions & 1 deletion modules/core/dependency/python-ihm/.codecov.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
ignore:
- test
- util
- **/_compat_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ jobs:
else
flake8 --ignore E402,W503,W504,N816
fi
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
7 changes: 5 additions & 2 deletions modules/core/dependency/python-ihm/ihm/dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1358,10 +1358,12 @@ def dump(self, system, writer):

def dump_summary(self, system, writer):
with writer.loop("_ihm_modeling_protocol",
["id", "protocol_name", "num_steps"]) as lp:
["id", "protocol_name", "num_steps",
"details"]) as lp:
for p in system._all_protocols():
lp.write(id=p._id,
protocol_name=p.name, num_steps=len(p.steps))
protocol_name=p.name, num_steps=len(p.steps),
details=p.details)

def dump_details(self, system, writer):
ordinal = itertools.count(1)
Expand Down Expand Up @@ -1657,6 +1659,7 @@ def dump_atoms(self, system, writer, add_ihm=True):
type_symbol=atom.type_symbol,
group_PDB='HETATM' if atom.het else 'ATOM',
label_atom_id=atom.atom_id,
label_alt_id=atom.alt_id,
label_comp_id=comp.id,
label_asym_id=atom.asym_unit._id,
label_entity_id=atom.asym_unit.entity._id,
Expand Down
4 changes: 3 additions & 1 deletion modules/core/dependency/python-ihm/ihm/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,10 @@ def _repr(self, obj):
# which isn't valid mmCIF syntax. _long_type = long only on Python 2.
elif isinstance(obj, _long_type):
return "%d" % obj
else:
elif isinstance(obj, str):
return repr(obj)
else:
return str(obj)


# Acceptable 'whitespace' characters in CIF
Expand Down
7 changes: 5 additions & 2 deletions modules/core/dependency/python-ihm/ihm/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,23 @@ class Atom(object):
:param float biso: Temperature factor or equivalent (if applicable)
:param float occupancy: Fraction of the atom type present
(if applicable)
:param float alt_id: Alternate conformation indicator
(if applicable)
"""

# Reduce memory usage
__slots__ = ['asym_unit', 'seq_id', 'atom_id', 'type_symbol',
'x', 'y', 'z', 'het', 'biso', 'occupancy']
'x', 'y', 'z', 'het', 'biso', 'occupancy', 'alt_id']

def __init__(self, asym_unit, seq_id, atom_id, type_symbol, x, y, z,
het=False, biso=None, occupancy=None):
het=False, biso=None, occupancy=None, alt_id=None):
self.asym_unit = asym_unit
self.seq_id, self.atom_id = seq_id, atom_id
self.type_symbol = type_symbol
self.x, self.y, self.z = x, y, z
self.het, self.biso = het, biso
self.occupancy = occupancy
self.alt_id = alt_id


class Model(object):
Expand Down
6 changes: 5 additions & 1 deletion modules/core/dependency/python-ihm/ihm/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ class Protocol(object):
Normally a protocol is passed to one or more :class:`~ihm.model.Model`
objects, although unused protocols can still be included in the file
if desired by adding them to :attr:`~ihm.System.orphan_protocols`.
:param str name: Optional name for the protocol
:param str details: Additional text describing the protocol
"""
def __init__(self, name=None):
def __init__(self, name=None, details=None):
self.name = name
self.details = details

#: All modeling steps (:class:`Step` objects)
self.steps = []
Expand Down
9 changes: 5 additions & 4 deletions modules/core/dependency/python-ihm/ihm/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1738,9 +1738,10 @@ class _ProtocolHandler(Handler):
category = '_ihm_modeling_protocol'
ignored_keywords = ['ordinal_id', 'struct_assembly_description']

def __call__(self, id, protocol_name, num_steps):
def __call__(self, id, protocol_name, num_steps, details):
p = self.sysr.protocols.get_by_id(id)
self.copy_if_present(p, locals(), mapkeys={'protocol_name': 'name'})
self.copy_if_present(p, locals(), mapkeys={'protocol_name': 'name'},
keys=['details'])


class _ProtocolDetailsHandler(Handler):
Expand Down Expand Up @@ -2136,7 +2137,7 @@ def _get_seq_id_from_auth(self, auth_seq_id, pdbx_pdb_ins_code, asym):
def __call__(self, pdbx_pdb_model_num, label_asym_id, b_iso_or_equiv,
label_seq_id, label_atom_id, type_symbol, cartn_x, cartn_y,
cartn_z, occupancy, group_pdb, auth_seq_id,
pdbx_pdb_ins_code, auth_asym_id, label_comp_id):
pdbx_pdb_ins_code, auth_asym_id, label_comp_id, label_alt_id):
# seq_id can be None for non-polymers (HETATM)
seq_id = self.get_int(label_seq_id)
# todo: handle fields other than those output by us
Expand Down Expand Up @@ -2164,7 +2165,7 @@ def __call__(self, pdbx_pdb_model_num, label_asym_id, b_iso_or_equiv,
asym_unit=asym, seq_id=our_seq_id, atom_id=label_atom_id,
type_symbol=type_symbol, x=float(cartn_x), y=float(cartn_y),
z=float(cartn_z), het=group != 'ATOM', biso=biso,
occupancy=occupancy)
occupancy=occupancy, alt_id=label_alt_id)
model.add_atom(a)

# Note any residues that have different seq_id and auth_seq_id
Expand Down
15 changes: 8 additions & 7 deletions modules/core/dependency/python-ihm/test/test_dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,7 +1762,7 @@ class MockObject(object):
num_models_end=2000, multi_scale=True, ensemble=False))
system.orphan_protocols.append(p1)

p2 = ihm.protocol.Protocol('sampling')
p2 = ihm.protocol.Protocol('sampling', details='extra details')
p2.steps.append(ihm.protocol.Step(
assembly=assembly, dataset_group=dsg2,
method='Replica exchange', num_models_begin=2000,
Expand All @@ -1779,8 +1779,9 @@ class MockObject(object):
_ihm_modeling_protocol.id
_ihm_modeling_protocol.protocol_name
_ihm_modeling_protocol.num_steps
1 equilibration 2
2 sampling 1
_ihm_modeling_protocol.details
1 equilibration 2 .
2 sampling 1 'extra details'
#
#
loop_
Expand Down Expand Up @@ -2357,7 +2358,7 @@ def test_model_dumper_atoms(self):
het=True),
ihm.model.Atom(asym_unit=asym, seq_id=2, atom_id='N',
type_symbol='N', x=4.0, y=5.0, z=6.0,
biso=42.0, occupancy=0.2)]
biso=42.0, occupancy=0.2, alt_id='A')]

dumper = ihm.dumper._ModelDumper()
dumper.finalize(system) # assign model/group IDs
Expand Down Expand Up @@ -2410,7 +2411,7 @@ def test_model_dumper_atoms(self):
_atom_site.ihm_model_id
ATOM 1 C C . ALA 1 1 ? X 1.000 2.000 3.000 . 9 X ALA . 1 1
HETATM 2 C CA . ALA 1 1 ? X 10.000 20.000 30.000 . 9 X ALA . 1 1
ATOM 3 N N . CYS 2 2 ? X 4.000 5.000 6.000 0.200 9 X CYS 42.000 1 1
ATOM 3 N N A CYS 2 2 ? X 4.000 5.000 6.000 0.200 9 X CYS 42.000 1 1
#
#
loop_
Expand All @@ -2431,7 +2432,7 @@ def test_model_dumper_atoms(self):
self.assertEqual(
out.split('\n')[44:47:2],
["ATOM 1 C C . ALA 1 0 ? X 1.000 2.000 3.000 . 9 X ALA . 1 1",
"ATOM 3 N N . CYS 2 1 ? X 4.000 5.000 6.000 "
"ATOM 3 N N A CYS 2 1 ? X 4.000 5.000 6.000 "
"0.200 9 X CYS 42.000 1 1"])

# With auth_seq_id map
Expand All @@ -2440,7 +2441,7 @@ def test_model_dumper_atoms(self):
self.assertEqual(
out.split('\n')[44:47:2],
["ATOM 1 C C . ALA 1 42 ? X 1.000 2.000 3.000 . 9 X ALA . 1 1",
"ATOM 3 N N . CYS 2 99 ? X 4.000 5.000 6.000 "
"ATOM 3 N N A CYS 2 99 ? X 4.000 5.000 6.000 "
"0.200 9 X CYS 42.000 1 1"])

def test_model_dumper_water_atoms(self):
Expand Down
4 changes: 2 additions & 2 deletions modules/core/dependency/python-ihm/test/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_simple_docking_example(self):
# can read it
with open(os.path.join(tmpdir, 'output.cif')) as fh:
contents = fh.readlines()
self.assertEqual(len(contents), 318)
self.assertEqual(len(contents), 319)
with open(os.path.join(tmpdir, 'output.cif')) as fh:
s, = ihm.reader.read(fh)

Expand Down Expand Up @@ -70,7 +70,7 @@ def test_ligands_water_example(self):
# can read it
with open(out) as fh:
contents = fh.readlines()
self.assertEqual(len(contents), 254)
self.assertEqual(len(contents), 255)
with open(out) as fh:
s, = ihm.reader.read(fh)
# Make sure that resulting Python objects are picklable
Expand Down
9 changes: 9 additions & 0 deletions modules/core/dependency/python-ihm/test/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import os
import unittest
import sys
try:
import numpy
except ImportError:
numpy = None

if sys.version_info[0] >= 3:
from io import StringIO
Expand Down Expand Up @@ -226,6 +230,11 @@ def test_repr(self):
# Literal . must be quoted to distinguish from the omitted value
self.assertEqual(w._repr('.foo'), ".foo")
self.assertEqual(w._repr('.'), "'.'")
# Make sure that numpy ints are treated like plain ints,
# not rendered as "np.int32(42)" or similar
if numpy is not None:
self.assertEqual(w._repr(numpy.int32(42)), '42')
self.assertEqual(w._repr(numpy.int64(42)), '42')

def test_reader_base(self):
"""Test Reader base class"""
Expand Down
8 changes: 6 additions & 2 deletions modules/core/dependency/python-ihm/test/test_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,12 +1320,14 @@ def test_protocol_handler(self):
_ihm_modeling_protocol.id
_ihm_modeling_protocol.protocol_name
_ihm_modeling_protocol.num_steps
1 Prot1 5
_ihm_modeling_protocol.details
1 Prot1 5 'extra details'
"""
for fh in cif_file_handles(cif):
s, = ihm.reader.read(fh)
p1, = s.orphan_protocols
self.assertEqual(p1.name, "Prot1")
self.assertEqual(p1.details, "extra details")
# no step objects read yet, num_steps ignored
self.assertEqual(len(p1.steps), 0)

Expand Down Expand Up @@ -1987,7 +1989,7 @@ def test_atom_site_handler(self):
_atom_site.pdbx_PDB_model_num
_atom_site.ihm_model_id
ATOM 1 N N . SER 1 A 54.401 -49.984 -35.287 . 1 A . 1 1
HETATM 2 C CA . SER . B 54.452 -48.492 -35.210 0.200 1 A 42.0 1 1
HETATM 2 C CA A SER . B 54.452 -48.492 -35.210 0.200 1 A 42.0 1 1
""")
s, = ihm.reader.read(fh)
m = s.state_groups[0][0][0][0]
Expand All @@ -2002,6 +2004,7 @@ def test_atom_site_handler(self):
self.assertEqual(a1.het, False)
self.assertIsNone(a1.biso)
self.assertIsNone(a1.occupancy)
self.assertIsNone(a1.alt_id)

self.assertEqual(a2.asym_unit._id, 'B')
self.assertEqual(a2.seq_id, 1)
Expand All @@ -2010,6 +2013,7 @@ def test_atom_site_handler(self):
self.assertEqual(a2.het, True)
self.assertAlmostEqual(a2.biso, 42.0, delta=1.0)
self.assertAlmostEqual(a2.occupancy, 0.2, delta=0.1)
self.assertEqual(a2.alt_id, 'A')

def test_atom_site_handler_auth_seq_id(self):
"""Test AtomSiteHandler handling of auth_seq_id and ins_code"""
Expand Down

0 comments on commit c95a236

Please sign in to comment.