Skip to content

Commit 707d46d

Browse files
committed
Add utility function to get representative model
Add a new method to System that returns a single "representative" model. If the user hasn't provided one explicitly, return the model containing the most chains instead. Closes #174.
1 parent 2eb2d75 commit 707d46d

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

ihm/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,27 @@ def _all_models(self):
268268
seen_models[model] = None
269269
yield group, model
270270

271+
def get_representative_model(self):
272+
"""Get a single :class:`~model.ModelRepresentative` that best
273+
represents the entire System. If no representatives have been
274+
provided, the :class:`~model.Model` containing the most chains
275+
is returned instead."""
276+
repmodel = None
277+
repmodel_chains = -1
278+
for mg in self._all_model_groups():
279+
if mg.representatives:
280+
return mg.representatives[0]
281+
for m in mg:
282+
asyms = frozenset(id(rep.asym_unit)
283+
for rep in m.representation)
284+
if len(asyms) > repmodel_chains:
285+
repmodel_chains = len(asyms)
286+
repmodel = m
287+
if repmodel is None:
288+
raise ValueError("No models")
289+
else:
290+
return repmodel
291+
271292
def update_locations_in_repositories(self, repos):
272293
"""Update all :class:`~ihm.location.Location` objects in the system
273294
that lie within a checked-out :class:`~ihm.location.Repository`

test/test_main.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,39 @@ def test_data_usage(self):
14101410
d = ihm.Disclaimer("foo", name="fooname", url="foourl")
14111411
self.assertEqual(d.type, "disclaimer")
14121412

1413+
def test_get_representative_model(self):
1414+
"""Test get_representative_model()"""
1415+
s = ihm.System()
1416+
# No models should raise an error
1417+
self.assertRaises(ValueError, s.get_representative_model)
1418+
1419+
e = ihm.Entity('AHC')
1420+
a1 = ihm.AsymUnit(e, 'foo')
1421+
a2 = ihm.AsymUnit(e, 'bar')
1422+
s.entities.append(e)
1423+
s.asym_units.extend((a1, a2))
1424+
s1 = ihm.representation.AtomicSegment(
1425+
a1, starting_model=None, rigid=True)
1426+
s2 = ihm.representation.AtomicSegment(
1427+
a2, starting_model=None, rigid=True)
1428+
m1 = ihm.model.Model(assembly=None, protocol=None,
1429+
representation=[s1])
1430+
m2 = ihm.model.Model(assembly=None, protocol=None,
1431+
representation=[s1, s2])
1432+
mg = ihm.model.ModelGroup((m1, m2))
1433+
state = ihm.model.State([mg])
1434+
s.state_groups.append(ihm.model.StateGroup([state]))
1435+
1436+
# m2 contains two chains to m1's one, so it should be selected
1437+
# by default
1438+
self.assertIs(s.get_representative_model(), m2)
1439+
1440+
# If we explicitly denote m1 as the representative, it should
1441+
# be returned instead
1442+
mr = ihm.model.ModelRepresentative(m1, "medoid")
1443+
mg.representatives.append(mr)
1444+
self.assertIs(s.get_representative_model(), mr)
1445+
14131446

14141447
if __name__ == '__main__':
14151448
unittest.main()

0 commit comments

Comments
 (0)