diff --git a/package/AUTHORS b/package/AUTHORS index c4ee0e250a..da88e54dbd 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -281,6 +281,7 @@ Chronological list of authors - Shubham Mittal - Charity Grey - Sai Udayagiri + - Apoorva Verma External code ------------- diff --git a/package/CHANGELOG b/package/CHANGELOG index 80385b3299..8ffa66069d 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -17,11 +17,14 @@ The rules for this file: ??/??/?? IAlibay, orbeckst, marinegor, tylerjereddy, ljwoods2, marinegor, spyke7, talagayev, tanii1125, BradyAJohnston, hejamu, jeremyleung521, harshitgajjela-droid, kunjsinha, aygarwal, jauy123, Dreamstick9, - ollyfutur, Amarendra22, charity-g, ParthUppal523 + ollyfutur, Amarendra22, charity-g, ParthUppal523, apoorva-01 * 2.11.0 Fixes + * `Merge()` no longer raises a TypeError on Universes that have a `cmaps` + attribute; cmaps are now combined like the other connection attributes + (bonds, angles, dihedrals, impropers) (Issue #3672). * The `principal_axes` method in :class:`Masses` now uses `np.linalg.eigh` instead of `np.linalg.eig`, improving numerical stability. This may lead to slightly different results from previous diff --git a/package/MDAnalysis/core/universe.py b/package/MDAnalysis/core/universe.py index 4b9ec247bd..e4534461b7 100644 --- a/package/MDAnalysis/core/universe.py +++ b/package/MDAnalysis/core/universe.py @@ -2162,7 +2162,7 @@ def Merge(*args): common_attrs = set.intersection( *[set(dir(ag.universe._topology)) for ag in args] ) - tops = set(["bonds", "angles", "dihedrals", "impropers"]) + tops = set(["bonds", "angles", "dihedrals", "impropers", "cmaps"]) attrs = [] diff --git a/testsuite/MDAnalysisTests/utils/test_modelling.py b/testsuite/MDAnalysisTests/utils/test_modelling.py index c014c9f4d0..2bf45502e5 100644 --- a/testsuite/MDAnalysisTests/utils/test_modelling.py +++ b/testsuite/MDAnalysisTests/utils/test_modelling.py @@ -329,3 +329,24 @@ def test_merge_without_topology(self, u): assert len(u_merge.atoms.angles) == 0 assert len(u_merge.atoms.dihedrals) == 0 assert len(u_merge.atoms.impropers) == 0 + + def test_merge_with_cmaps(self, u): + # cmaps are a connection attribute like bonds/angles, so Merge() must + # route them through the connection path rather than treating them as a + # plain array (Issue #3672). + u.add_TopologyAttr( + "cmaps", [[0, 1, 2, 3, 4], [100, 101, 102, 103, 104]] + ) + + ag1 = u.atoms[:20] + ag2 = u.atoms[100:110] + u_merge = MDAnalysis.Merge(ag1, ag2) + + # Both cmaps lie entirely within their atomgroup, so both survive and + # are renumbered against the merged universe (ag2 is offset by len(ag1)). + assert hasattr(u_merge.atoms, "cmaps") + assert len(u_merge.atoms.cmaps) == 2 + merged = sorted( + tuple(int(i) for i in c.indices) for c in u_merge.atoms.cmaps + ) + assert merged == [(0, 1, 2, 3, 4), (20, 21, 22, 23, 24)]