Skip to content

Commit daa6b81

Browse files
committed
Don't create segments for ResidueFeature
ResidueFeature's mmCIF table already explicitly lists the seq_id range, asym_id and entity_id used by the restraint; it doesn't use segment_id. Thus, we shouldn't create a segment for each such feature. Closes #175.
1 parent 8f3c850 commit daa6b81

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

ihm/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,16 +626,17 @@ def _all_citations(self):
626626
def _all_entity_ranges(self):
627627
"""Iterate over all Entity ranges in the system (these may be
628628
:class:`Entity`, :class:`AsymUnit`, :class:`EntityRange` or
629-
:class:`AsymUnitRange` objects).
629+
:class:`AsymUnitRange` objects) that will be given a unique ID.
630630
Note that we don't include self.entities or self.asym_units here,
631631
as we only want ranges that were actually used.
632+
We also don't include ranges used in ResidueFeature, as that
633+
explicitly states the range in the mmCIF table, not by reference to
634+
``ihm_entity_poly_segment``.
632635
Duplicates may be present."""
633636
return (itertools.chain(
634637
(sm.asym_unit for sm in self._all_starting_models()),
635638
(seg.asym_unit for seg in self._all_segments()),
636639
(comp for a in self._all_assemblies() for comp in a),
637-
(comp for f in self._all_features()
638-
for comp in f._all_entities_or_asyms()),
639640
(d.asym_unit for d in self._all_densities())))
640641

641642
def _all_multi_state_schemes(self):

test/test_dumper.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,11 +3091,15 @@ def test_entity_poly_segment_dumper(self):
30913091
a1._id = 'X'
30923092
system.entities.extend((e1, e2, e3))
30933093
system.asym_units.append(a1)
3094-
res1 = e2.residue(1)
3095-
res2 = e2.residue(2)
3096-
system.orphan_features.append(ihm.restraint.ResidueFeature([e2]))
3097-
system.orphan_features.append(ihm.restraint.ResidueFeature([res2]))
3098-
system.orphan_features.append(ihm.restraint.NonPolyFeature([e3]))
3094+
rng1 = a1(1,2)
3095+
rng2 = a1(3,4)
3096+
3097+
s1 = ihm.representation.ResidueSegment(
3098+
rng1, starting_model=None,
3099+
rigid=False, primitive='sphere')
3100+
r1 = ihm.representation.Representation((s1,), name='foo',
3101+
details='bar')
3102+
system.orphan_representations.append(r1)
30993103

31003104
system._make_complete_assembly()
31013105

@@ -3107,14 +3111,11 @@ def test_entity_poly_segment_dumper(self):
31073111
# e1 isn't directly used in anything (a1 is used instead, in the
31083112
# assembly) so should have no range ID
31093113
self.assertFalse(hasattr(e1, '_range_id'))
3110-
self.assertEqual(a1._range_id, 1)
3111-
# e2 is use, in a ResidueFeature, so should have a range ID
3112-
self.assertEqual(e2._range_id, 2)
3113-
# non-polymers don't have ranges
3114-
self.assertEqual(e3._range_id, None)
3115-
# res2 should have been assigned a range, but not res1
3116-
self.assertFalse(hasattr(res1, '_range_id'))
3117-
self.assertEqual(res2._range_id, 3)
3114+
self.assertEqual(a1._range_id, 2)
3115+
# rng1 is use, in a ResidueSegment, so should have a range ID
3116+
self.assertEqual(rng1._range_id, 1)
3117+
# rng2 is not in use
3118+
self.assertFalse(hasattr(rng2, '_range_id'))
31183119

31193120
out = _get_dumper_output(dumper, system)
31203121
self.assertEqual(out, """#
@@ -3125,9 +3126,8 @@ def test_entity_poly_segment_dumper(self):
31253126
_ihm_entity_poly_segment.seq_id_end
31263127
_ihm_entity_poly_segment.comp_id_begin
31273128
_ihm_entity_poly_segment.comp_id_end
3128-
1 1 1 4 ALA ASP
3129-
2 2 1 3 ALA GLY
3130-
3 2 2 2 CYS CYS
3129+
1 1 1 2 ALA HIS
3130+
2 1 1 4 ALA ASP
31313131
#
31323132
""")
31333133

@@ -3142,8 +3142,12 @@ def test_entity_poly_segment_dumper_bad_range(self):
31423142
# Disable construction-time check so that we
31433143
# can see dump time check
31443144
e1._range_check = False
3145-
system.orphan_features.append(
3146-
ihm.restraint.ResidueFeature([e1(*badrng)]))
3145+
s1 = ihm.representation.ResidueSegment(
3146+
e1(*badrng), starting_model=None,
3147+
rigid=False, primitive='sphere')
3148+
r1 = ihm.representation.Representation((s1,), name='foo',
3149+
details='bar')
3150+
system.orphan_representations.append(r1)
31473151
e1._range_check = True
31483152

31493153
dumper = ihm.dumper._EntityDumper()

test/test_main.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import ihm.model
1212
import ihm.source
1313
import ihm.flr
14+
import ihm.restraint
1415
import ihm.multi_state_scheme
1516

1617

@@ -1172,6 +1173,7 @@ class MockObject:
11721173
s.asym_units.append(a1)
11731174
e1rng = e1(1, 3)
11741175
a1rng = a1(1, 2)
1176+
a1rng2 = a1(3, 4)
11751177

11761178
sm1 = MockObject()
11771179
sm1.asym_unit = e1rng
@@ -1184,6 +1186,10 @@ class MockObject:
11841186
rep.append(seg1)
11851187
s.orphan_representations.append(rep)
11861188

1189+
# Ranges listed in ResidueFeature should not be included
1190+
# in _all_entity_ranges()
1191+
s.orphan_features.append(ihm.restraint.ResidueFeature([a1rng2]))
1192+
11871193
asmb1 = ihm.Assembly([e1, a1])
11881194
s.orphan_assemblies.append(asmb1)
11891195

0 commit comments

Comments
 (0)